How to move cursor from one text field to another automatically in swift ios programmatically?

Set textField delegate and add target:

override func viewDidLoad() {
        super.viewDidLoad()

        first.delegate = self
        second.delegate = self
        third.delegate = self
        fourth.delegate = self


        first.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
        second.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
        third.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
        fourth.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
    }

Now when text changes change textField

func textFieldDidChange(textField: UITextField){

    let text = textField.text

    if text?.utf16.count >= 1{
        switch textField{
        case first:
            second.becomeFirstResponder()
        case second:
            third.becomeFirstResponder()
        case third:
            fourth.becomeFirstResponder()
        case fourth:
            fourth.resignFirstResponder()
        default:
            break
        }
    }else{

    }
}

And lastly when user start editing clear textField

extension ViewController: UITextFieldDelegate{
    func textFieldDidBeginEditing(textField: UITextField) {
        textField.text = ""
    }
}

update Solution For Swift 5

In This solution, You will go to next Field. And When You Press Erase will come at previous text field.

Step 1: Set Selector for Text Field

override func viewDidLoad() {
        super.viewDidLoad()

         otpTextField1.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
    otpTextField2.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
    otpTextField3.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
    otpTextField4.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
        
    }

Step 2: Now We will handle move next text Field and Erase text Field.

@objc func textFieldDidChange(textField: UITextField){
        let text = textField.text
        if  text?.count == 1 {
            switch textField{
            case otpTextField1:
                otpTextField2.becomeFirstResponder()
            case otpTextField2:
                otpTextField3.becomeFirstResponder()
            case otpTextField3:
                otpTextField4.becomeFirstResponder()
            case otpTextField4:
                otpTextField4.resignFirstResponder()
            default:
                break
            }
        }
        if  text?.count == 0 {
            switch textField{
            case otpTextField1:
                otpTextField1.becomeFirstResponder()
            case otpTextField2:
                otpTextField1.becomeFirstResponder()
            case otpTextField3:
                otpTextField2.becomeFirstResponder()
            case otpTextField4:
                otpTextField3.becomeFirstResponder()
            default:
                break
            }
        }
        else{

        }
    }

Important Note: Don't Forget To set Delegate.


Swift 3 code to move the cursor from one field to another automatically in OTP(One Time Password) fields.

    //Add all outlet in your code. 
    @IBOutlet weak var otpbox1: UITextField!
    @IBOutlet weak var otpbox2: UITextField!
    @IBOutlet weak var otpbox3: UITextField!
    @IBOutlet weak var otpbox4: UITextField!
    @IBOutlet weak var otpbox5: UITextField!
    @IBOutlet weak var otpbox6: UITextField!
    // Add the delegate in viewDidLoad
    func viewDidLoad() {
        super.viewDidLoad()
        otpbox1?.delegate = self
        otpbox2?.delegate = self
        otpbox3?.delegate = self
        otpbox4?.delegate = self
        otpbox5?.delegate = self
        otpbox6?.delegate = self
    }
    func textField(_ textField: UITextField, shouldChangeCharactersIn range:NSRange, replacementString string: String) -> Bool {
        // Range.length == 1 means,clicking backspace
    if (range.length == 0){
        if textField == otpbox1 {
            otpbox2?.becomeFirstResponder()
        }
        if textField == otpbox2 {
            otpbox3?.becomeFirstResponder()
        }
        if textField == otpbox3 {
            otpbox4?.becomeFirstResponder()
        }
        if textField == otpbox4 {
            otpbox5?.becomeFirstResponder()
        }
        if textField == otpbox5 {
            otpbox6?.becomeFirstResponder()
        }
        if textField == otpbox6 {
            otpbox6?.resignFirstResponder() /*After the otpbox6 is filled we capture the All the OTP textField and do the server call. If you want to capture the otpbox6 use string.*/
            let otp = "\((otpbox1?.text)!)\((otpbox2?.text)!)\((otpbox3?.text)!)\((otpbox4?.text)!)\((otpbox5?.text)!)\(string)"
        }
        textField.text? = string
        return false
    }else if (range.length == 1) {
            if textField == otpbox6 {
                otpbox5?.becomeFirstResponder()
            }
            if textField == otpbox5 {
                otpbox4?.becomeFirstResponder()
            }
            if textField == otpbox4 {
                otpbox3?.becomeFirstResponder()
            }
            if textField == otpbox3 {
                otpbox2?.becomeFirstResponder()
            }
            if textField == otpbox2 {
                otpbox1?.becomeFirstResponder()
            }
            if textField == otpbox1 {
                otpbox1?.resignFirstResponder()
            }
            textField.text? = ""
            return false
    }
    return true
    }