Search code examples
swiftuitextfielddelegate

shouldChangeCharactersInRange multiple text fields gets frozen


Updated code bellow with solution.

This works with as many fields you want.

It also fixes the textfield frozen issue when the method returns false.

The line bellow is what guides the method to return true after returns false.

newString = currentString.stringByReplacingCharactersInRange(range, withString: string)

On view did load (this will add an identifier to each field so you can identify within the method what field is being used - it is an Int())

    emailAddressField.tag = 1
    userPasswordField.tag = 2

On delegate method

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    var maxLength = Int()
    var newString = NSString()
    var currentString = NSString()

    println("MY TAG \(textField.tag)")

    switch textField.tag {

    case 1:
        println("CASE 1 \(range)")

        maxLength = 16
        currentString = emailAddressField.text
       newString = currentString.stringByReplacingCharactersInRange(range, withString: string)

    case 2:
        println("CASE 2 \(range)")

        maxLength = 8
        currentString = userPasswordField.text
        newString = currentString.stringByReplacingCharactersInRange(range, withString: string)

    default:
        println("Didn't detect any field")

    }
    return newString.length <= maxLength

}

Solution

  • The issue is that the delegate method shouldChangeCharactersInRange is used for both text fields and in your implementation you're returning false as soon as one of the text fields reaches its limit which ultimately makes both text fields deny further input. To resolve this you need to check the method's textField parameter to identify which text field the method is called for.

    One of the possible ways to do this is to set up tags on your two text fields, for instance in viewDidLoad,

    override func viewDidLoad() {
        ...
        emailAddressField.tag = EMAIL_ADDRESS_TEXTFIELD // e.g. 0
        userPasswordField.tag = USER_PASSWORD_TEXTFIELD // e.g. 1
    }
    

    and then act upon the tag of the text field supplied to the delegate method

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        let newString = textField.text!.stringByReplacingCharactersInRange(range, withString: string)
    
        if textField.tag == EMAIL_ADDRESS_TEXTFIELD && count(newString) + 1 == 30 {
            return false
        }
    
        if textField.tag == USER_PASSWORD_TEXTFIELD && count(newString) + 1 == 11 {
            return false
        }
    
        return true
    }