Search code examples
iosswift2uitextfieldlimituitextfielddelegate

How do I limit text lengths for different UITextFields in Swift?


I have an iOS Xcode 7.3 Swift2 project I'm working on. It has different UITextFields that are limited to 3 digits, specifically only numbers. They are assigned to the UITextFieldDelegate and it's working well.

Here is where I limit them:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    guard let text = textField.text else { return true }
    let newLength = text.characters.count + string.characters.count - range.length
    let limitLength = 3
    if newLength > limitLength {
        return false
    }

    let numberOnly = NSCharacterSet.init(charactersInString: "0123456789")
    let stringFromTextField = NSCharacterSet.init(charactersInString: string)
    let strValid = numberOnly.isSupersetOfSet(stringFromTextField)

    return strValid
}

However, some of the UITextFields need to be limited to numbers still AND also limited to a single digit, how can I institute this in the section above, only for those specific UITextFields?

The names of the UITextFields that need to be single digits are:

widthInches
lengthInches

I tried placing this after the first guard section with no luck:

guard let text2 = widthInches.text else { return true }
let newLength2 = text2.characters.count + string.characters.count - range.length
let limitLength2 = 3
if newLength2 > limitLength2 {
    return false
}

Solution

  • The function shouldChangeCharactersInRange passes in the particular textField as one of its parameters. You can look at that and see if it points to the same instance as the ones you want to shorten, like this:

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
        guard let text = textField.text else { return true }
        var limitLength = 3
        if textField == widthInches || textField == lengthInches {
          limitLength = 1
        }
    
        let newLength = text.characters.count + string.characters.count - range.length
        if newLength > limitLength {
          return false
        }
    
        let numberOnly = NSCharacterSet.init(charactersInString: "0123456789")
        let stringFromTextField = NSCharacterSet.init(charactersInString: string)
        let strValid = numberOnly.isSupersetOfSet(stringFromTextField)
    
        return strValid
      }
    

    Assuming all other requirements are the same (numbers only) this will do the trick.

    There are other ways, for example - you could subclass UITextField and add a limitLength field, then use that field in the delegate, but that's probably overkill for just 2 exceptions.