Oren Edrich
Oren Edrich

Reputation: 674

Switching to next UITextField when character limit is reached

I have three text fields to enter in a phone number. I am trying to set the character limit for each textfield to three characters and once this is reached switch to a new textfield.

I saw online to use this code to limit the characters:

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

    let currentCharacterCount = textField.text?.characters.count ?? 0
    if (range.length + range.location > currentCharacterCount){
        return false
    }
    let newLength = currentCharacterCount + string.characters.count - range.length
    return newLength <= 25
}

and to use this to switch to typing on a new textfield:

.didbecomefirstresponder()

but I am not sure how to limit a text field to 3 characters and then switch to the next field.

Upvotes: 0

Views: 1692

Answers (3)

MuSoundiX
MuSoundiX

Reputation: 88

I find Pierce's answers too complex and anas.p's answer doesn't work for me like it's supposed to. My Swift 5 solution:

override func viewDidLoad() {
    textField1.addTarget(self, action: #selector(textFieldDidChange1), for:.editingChanged)
    textField2.addTarget(self, action: #selector(textFieldDidChange2), for:.editingChanged)
}

@objc func textFieldDidChange1() {
        // After 2 characters are typed, immediately jump to textField2
        if (textField1.text?.count == 2) {
            self.textField2.becomeFirstResponder()
        }
    }

@objc func textFieldDidChange2() {
    if (textField2.text?.count == 2) {
        self.textField3.becomeFirstResponder()
    }
}

Upvotes: 0

anas.p
anas.p

Reputation: 2286

This is my code, how I solve this:

The three textfields are:

@IBOutlet var txtField1: UITextField!
@IBOutlet var txtField2: UITextField!
@IBOutlet var txtField3: UITextField!

import UITextFieldDelegate in to your class and set the delegate to self for all the textfields.

And use this method to change focus.

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

    let currentCharacterCount = ((textField.text?.characters.count)! + string.characters.count) - 1

    switch (textField, currentCharacterCount) {
    case (self.txtField1, 3):
        self.txtField2.becomeFirstResponder()
    case (self.txtField2, 7):
        self.txtField3.becomeFirstResponder()
    default:
        break
    }

    return true
}

Here I set character count 3 for the first textfield, and 7 for second textfield.

Upvotes: 2

Pierce
Pierce

Reputation: 3158

You could use the delegate method for UITextField shouldChangeCharactersInRange. You'd have to do a little setup work though. Here's an example that creates 3 textFields, conforms to the UITextFieldDelegate, and does something similar to what you're describing.

class ViewController: UIViewController, UITextFieldDelegate {


var max = 3
var fields:[UITextField] = []

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


    // This is just an example to layout 3 text fields.
    for i in 0 ..< 3 {
        let field = UITextField()
        view.addSubview(field)
        field.delegate = self
        field.borderStyle = .roundedRect
        field.font = UIFont(name: "AvenirNext-Regular", size: 15.0)
        field.textColor = UIColor.black
        field.frame = CGRect(x: view.bounds.width/2 - 100, y: 100 + (150*CGFloat(i)), width: 200, height: 50)
        fields.append(field)
    }


}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    // Make sure the field has non-nil text
    if let text = textField.text {
        // Check if the text length has reached max limit
        if text.characters.count > (max-1) {
            // Get index of field from fields array
            if let index = fields.index(of: textField) {
                // Make sure it's not the last field in the array else return false
                if index < fields.count-1 {
                    // Make the next field in the array become first responder if it's text is non-nil and it's text's character count is less than desired max
                    if fields[index+1].text != nil && fields[index+1].text!.characters.count < (max-1) {
                        fields[index+1].becomeFirstResponder()
                    } else {
                        return false
                    }
                } else {
                    return false
                }
            }
        }
    }
    return true
}

}

Upvotes: 1

Related Questions