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

13

18
    func textFieldDidBeginEditing(textField: UITextField) {
    scrlView.setContentOffset(CGPointMake(0, textField.frame.origin.y-70), animated: true)


    if(textField == firstDigit){

        textField.becomeFirstResponder()
        secondDigit.resignFirstResponder()
    }


    else if(textField == secondDigit){

        textField.becomeFirstResponder()
        thirdDigit.resignFirstResponder()
    }

    else if(textField == thirdDigit){
        //textField.becomeFirstResponder()
        fourthDigit.becomeFirstResponder()
    }

I am using four textfields for OTP entry in which only one number can be entered at a time. After entering the number I need to move the cursor automatically to next textfield.

Rebba answered 11/2, 2016 at 5:57 Comment(3)
github.com/hackiftekhar/IQKeyboardManager Please add this library into your project using pods and done. You don't need to code anything or add something else. This library manages all by itself.Interlining
see this for help : https://mcmap.net/q/668777/-textfield-backspace-action-identify-when-textfield-is-empty/…Rocketeer
Try this:- github.com/Datt1994/DPOTPViewGravimetric
S
33

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 = ""
    }
}
Seymourseys answered 11/2, 2016 at 6:21 Comment(3)
If we want to auto fetch the OTP(if we use single textfield) we need to use otpTextField.textContentType = .oneTimeCode if we use multiple textfiled, how should we achieve this ?Paulita
Swift 4.2 didBeginEditing has been changed to: func textFieldDidBeginEditing(_ textField: UITextField) { textField.text = "" }Ellora
@Paulita Did you find any solution for otp with multiple textfields how to move cursor to next?Rebeckarebeka
C
27

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.

Chen answered 7/3, 2018 at 11:8 Comment(5)
add otpTextField*.selectAll(nil) for auto select textDexamethasone
Thank you so much for such fruitful answer!Phyla
After erasing, we are not able to move to the next text field until pressed manuallyDisguise
@AbhinavJha check text?.count == 0 is calling on Erase Press.?Chen
@AbhinavJha have you set the Delegate?Chen
E
5

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
    }
Effluence answered 4/7, 2018 at 9:14 Comment(0)
E
4

This is similar to how UberEats has their otp fields. You can just copy and paste this into a file and run it to see how it works. But don't forget to add the MyTextField class or it won't work.

If you want it to automatically to move to the next textfield after a number is entered and still be able to move backwards if the back button is pressed WHILE the textField is empty this will help you.

Like the very first thing I said, this is similar to how UberEats has their sms textFields working. You can't just randomly press a textField and select it. Using this you can only move forward and backwards. The ux is subjective but if Uber uses it the ux must be valid. I say it's similar because they also have a gray box covering the textField so I'm not sure what's going on behind it. This was the closest I could get.

First your going to have to subclass UITextField using this answer to detect when the backspace button is pressed. When the back button is pressed your going to erase everything inside that field AND the previous field then jump to the previous field.

Second your going to have to prevent the user from being able to select the left side of the cursor once a char is inside the textField using this answer. You override the method in the same subClass from the first step.

Third you need to detect which textField is currently active using this answer

Fourth your going to have to run some checks inside func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool using this YouTube tutorial. I added some things to his work.

I'm doing everything programmatically so you can copy and paste the entire code into a project and run it

First create a subClass of UITextField and name it MyTextField:

protocol MyTextFieldDelegate: class {
    func textFieldDidDelete()
}

// 1. subclass UITextField and create protocol for it to know when the backButton is pressed
class MyTextField: UITextField {

    weak var myDelegate: MyTextFieldDelegate? // make sure to declare this as weak to prevent a memory leak/retain cycle

    override func deleteBackward() {
        super.deleteBackward()
        myDelegate?.textFieldDidDelete()
    }

    // when a char is inside the textField this keeps the cursor to the right of it. If the user can get on the left side of the char and press the backspace the current char won't get deleted
    override func closestPosition(to point: CGPoint) -> UITextPosition? {
        let beginning = self.beginningOfDocument
        let end = self.position(from: beginning, offset: self.text?.count ?? 0)
        return end
    }
}

Second inside the class with the OTP textfields, set the class to use the UITextFieldDelegate and the MyTextFieldDelegate, then create a class property and name it activeTextField. When whichever textField becomes active inside textFieldDidBeginEditing you set the activeTextField to that. In viewDidLoad set all the textFields to use both delegates.

Make sure the First otpTextField is ENABLED and the second, third, and fourth otpTextFields are ALL initially DIASABLED

import UIKit

// 2. set the class to BOTH Delegates
class ViewController: UIViewController, UITextFieldDelegate, MyTextFieldDelegate {

    let staticLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont.systemFont(ofSize: 17)
        label.text = "Enter the SMS code sent to your phone"
        return label
    }()

    // 3. make each textField of type MYTextField
    let otpTextField1: MyTextField = {
        let textField = MyTextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.font = UIFont.systemFont(ofSize: 25)
        textField.autocorrectionType = .no
        textField.keyboardType = .numberPad
        textField.textAlignment = .center
        // **important this is initially ENABLED
        return textField
    }()

    let otpTextField2: MyTextField = {
        let textField = MyTextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.font = UIFont.systemFont(ofSize: 25)
        textField.autocorrectionType = .no
        textField.keyboardType = .numberPad
        textField.textAlignment = .center
        textField.isEnabled = false // **important this is initially DISABLED
        return textField
    }()

    let otpTextField3: MyTextField = {
        let textField = MyTextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.font = UIFont.systemFont(ofSize: 25)
        textField.autocorrectionType = .no
        textField.keyboardType = .numberPad
        textField.textAlignment = .center
        textField.isEnabled = false // **important this is initially DISABLED
        return textField
    }()

    let otpTextField4: MyTextField = {
        let textField = MyTextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.font = UIFont.systemFont(ofSize: 25)
        textField.autocorrectionType = .no
        textField.keyboardType = .numberPad
        textField.textAlignment = .center
        textField.isEnabled = false // **important this is initially DISABLED
        return textField
    }()

    // 4. create this property to know which textField is active. Set it in step 8 and use it in step 9
    var activeTextField = UITextField()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        // 5. set the regular UItextField delegate to each textField
        otpTextField1.delegate = self
        otpTextField2.delegate = self
        otpTextField3.delegate = self
        otpTextField4.delegate = self

        // 6. set the subClassed textField delegate to each textField
        otpTextField1.myDelegate = self
        otpTextField2.myDelegate = self
        otpTextField3.myDelegate = self
        otpTextField4.myDelegate = self

        configureAnchors()

        // 7. once the screen appears show the keyboard 
        otpTextField1.becomeFirstResponder()
    }

// 8. when a textField is active set the activeTextField property to that textField
func textFieldDidBeginEditing(_ textField: UITextField) {

    activeTextField = textField
}

// 9. when the backButton is pressed, the MyTextField delegate will get called. The activeTextField will let you know which textField the backButton was pressed in. Depending on the textField certain textFields will become enabled and disabled.
func textFieldDidDelete() {

    if activeTextField == otpTextField1 {
        print("backButton was pressed in otpTextField1")
        // do nothing
    }

    if activeTextField == otpTextField2 {
        print("backButton was pressed in otpTextField2")
        otpTextField2.isEnabled = false
        otpTextField1.isEnabled = true
        otpTextField1.becomeFirstResponder()
        otpTextField1.text = ""
    }

    if activeTextField == otpTextField3 {
        print("backButton was pressed in otpTextField3")
        otpTextField3.isEnabled = false
        otpTextField2.isEnabled = true
        otpTextField2.becomeFirstResponder()
        otpTextField2.text = ""
    }

    if activeTextField == otpTextField4 {
        print("backButton was pressed in otpTextField4")
        otpTextField4.isEnabled = false
        otpTextField3.isEnabled = true
        otpTextField3.becomeFirstResponder()
        otpTextField3.text = ""
    }
}

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

    if let text = textField.text {

        // 10. when the user enters something in the first textField it will automatically adjust to the next textField and in the process do some disabling and enabling. This will proceed until the last textField
        if (text.count < 1) && (string.count > 0) {

            if textField == otpTextField1 {
                otpTextField1.isEnabled = false
                otpTextField2.isEnabled = true
                otpTextField2.becomeFirstResponder()
            }

            if textField == otpTextField2 {
                otpTextField2.isEnabled = false
                otpTextField3.isEnabled = true
                otpTextField3.becomeFirstResponder()
            }

            if textField == otpTextField3 {
                otpTextField3.isEnabled = false
                otpTextField4.isEnabled = true
                otpTextField4.becomeFirstResponder()
            }

            if textField == otpTextField4 {
                // do nothing or better yet do something now that you have all four digits for the sms code. Once the user lands on this textField then the sms code is complete
            }

            textField.text = string
            return false

        } // 11. if the user gets to the last textField and presses the back button everything above will get reversed
        else if (text.count >= 1) && (string.count == 0) {

            if textField == otpTextField2 {
                otpTextField2.isEnabled = false
                otpTextField1.isEnabled = true
                otpTextField1.becomeFirstResponder()
                otpTextField1.text = ""
            }

            if textField == otpTextField3 {
                otpTextField3.isEnabled = false
                otpTextField2.isEnabled = true
                otpTextField2.becomeFirstResponder()
                otpTextField2.text = ""
            }

            if textField == otpTextField4 {
                otpTextField4.isEnabled = false
                otpTextField3.isEnabled = true
                otpTextField3.becomeFirstResponder()
                otpTextField3.text = ""
            }

            if textField == otpTextField1 {
                // do nothing
            }

            textField.text = ""
            return false

        } // 12. after pressing the backButton and moving forward again you will have to do what's in step 10 all over again
        else if text.count >= 1 {

            if textField == otpTextField1 {
                otpTextField1.isEnabled = false
                otpTextField2.isEnabled = true
                otpTextField2.becomeFirstResponder()
            }

            if textField == otpTextField2 {
                otpTextField2.isEnabled = false
                otpTextField3.isEnabled = true
                otpTextField3.becomeFirstResponder()
            }

            if textField == otpTextField3 {
                otpTextField3.isEnabled = false
                otpTextField4.isEnabled = true
                otpTextField4.becomeFirstResponder()
            }

            if textField == otpTextField4 {
                // do nothing or better yet do something now that you have all four digits for the sms code. Once the user lands on this textField then the sms code is complete
            }

            textField.text = string
            return false
        }
    }
    return true
}

//**Optional** For a quick setup use this below. Here is how to add a gray line to the textFields and here are the anchors:
    // if your app supports portrait and horizontal your going to have to make some adjustments to this every time the phone rotates
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        addBottomLayerTo(textField: otpTextField1)
        addBottomLayerTo(textField: otpTextField2)
        addBottomLayerTo(textField: otpTextField3)
        addBottomLayerTo(textField: otpTextField4)
    }

    // this adds a lightGray line at the bottom of the textField
    func addBottomLayerTo(textField: UITextField) {
        let layer = CALayer()
        layer.backgroundColor = UIColor.lightGray.cgColor
        layer.frame = CGRect(x: 0, y: textField.frame.height - 2, width: textField.frame.width, height: 2)
        textField.layer.addSublayer(layer)
    }

    func configureAnchors() {

        view.addSubview(staticLabel)

        view.addSubview(otpTextField1)
        view.addSubview(otpTextField2)
        view.addSubview(otpTextField3)
        view.addSubview(otpTextField4)

        let width = view.frame.width / 5

        staticLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 15).isActive = true
        staticLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10).isActive = true
        staticLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -10).isActive = true

        // textField 1
        otpTextField1.topAnchor.constraint(equalTo: staticLabel.bottomAnchor, constant: 10).isActive = true
        otpTextField1.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10).isActive = true
        otpTextField1.widthAnchor.constraint(equalToConstant: width).isActive = true
        otpTextField1.heightAnchor.constraint(equalToConstant: width).isActive = true

        // textField 2
        otpTextField2.topAnchor.constraint(equalTo: staticLabel.bottomAnchor, constant: 10).isActive = true
        otpTextField2.leadingAnchor.constraint(equalTo: otpTextField1.trailingAnchor, constant: 10).isActive = true
        otpTextField2.widthAnchor.constraint(equalTo: otpTextField1.widthAnchor).isActive = true
        otpTextField2.heightAnchor.constraint(equalToConstant: width).isActive = true

        // textField 3
        otpTextField3.topAnchor.constraint(equalTo: staticLabel.bottomAnchor, constant: 10).isActive = true
        otpTextField3.leadingAnchor.constraint(equalTo: otpTextField2.trailingAnchor, constant: 10).isActive = true
        otpTextField3.widthAnchor.constraint(equalTo: otpTextField1.widthAnchor).isActive = true
        otpTextField3.heightAnchor.constraint(equalToConstant: width).isActive = true

        // textField 4
        otpTextField4.topAnchor.constraint(equalTo: staticLabel.bottomAnchor, constant: 10).isActive = true
        otpTextField4.leadingAnchor.constraint(equalTo: otpTextField3.trailingAnchor, constant: 10).isActive = true
        otpTextField4.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -10).isActive = true
        otpTextField4.widthAnchor.constraint(equalTo: otpTextField1.widthAnchor).isActive = true
        otpTextField4.heightAnchor.constraint(equalToConstant: width).isActive = true
     }
}

enter image description here

This is separate from the answer above but if you need to add multiple characters to each otpTextField then follow this answer.

Ellora answered 8/2, 2019 at 22:53 Comment(4)
i want first textfield to show 3 characters, second to show 4 , third to show 7 and fourth textfield to show 1 character. how can i achieve this? please helpCamiecamila
where should i add this. can you please explain, or should i open a new question and you can answer there?Camiecamila
Ask a new questionEllora
I’ll look at it laterEllora
C
3

Firstly we'll need to set the tag for the UITextField;

func textFieldShouldReturnSingle(_ textField: UITextField , newString : String)
{
    let nextTag: Int = textField.tag + 1

    let nextResponder: UIResponder? = textField.superview?.superview?.viewWithTag(nextTag)
    textField.text = newString
    if let nextR = nextResponder
    {
        // Found next responder, so set it.
        nextR.becomeFirstResponder()
    }
    else
    {
        // Not found, so remove keyboard.
        textField.resignFirstResponder()
    }
}

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

    let newString = ((textField.text)! as NSString).replacingCharacters(in: range, with: string)

    let newLength = newString.characters.count

    if newLength == 1 {
        textFieldShouldReturnSingle(textField , newString : newString)
        return false
    }

    return true
}

Note: The UITextField takes only one character in number format, which is in OTP format.

Clapboard answered 16/5, 2017 at 12:39 Comment(0)
Y
1

Objective c and Swift 4.2 to move the cursor from one field to another automatically in OTP(One Time Password) fields

Here i am taking one view controller view controller screen design stackview inside textfileds[![][1]]1

Then give the Tag values for each TextFiled.Those related reference images are shown below Enter tag value for first textfiled --> 1,2ndTextfiled ---->2,3rd TextFiled --->3   4rth TextFiled---->4

enter image description here

Enter tag value for first textfiled --> 1,2ndTextfiled ---->2,3rd TextFiled --->3 4rth TextFiled---->4

Then assign Textfiled Delegates and write below code and see the magic

 - (BOOL)textField:(UITextField *)textField 
shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString 
 *)string
 {
 if ((textField.text.length < 1) && (string.length > 0))
 {
    NSInteger nextTag = textField.tag + 1;
    UIResponder* nextResponder = [textField.superview 
  viewWithTag:nextTag];
    if (! nextResponder){
        [textField resignFirstResponder];
    }
    textField.text = string;
    if (nextResponder)
        [nextResponder becomeFirstResponder];
    return NO;

 }else if ((textField.text.length >= 1) && (string.length == 0)){
    // on deleteing value from Textfield

    NSInteger prevTag = textField.tag - 1;
    // Try to find prev responder
    UIResponder* prevResponder = [textField.superview 
 viewWithTag:prevTag];
    if (! prevResponder){
        [textField resignFirstResponder];
    }
    textField.text = string;
    if (prevResponder)
        // Found next responder, so set it.
        [prevResponder becomeFirstResponder];

    return NO;
}
return YES;

}

swift4.2 version code

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



    if textField.text!.count < 1 && string.count > 0 {
        let tag = textField.tag + 1;
        let nextResponder = textField.superview?.viewWithTag(tag)

        if   (nextResponder != nil){
            textField.resignFirstResponder()

        }
        textField.text = string;
        if (nextResponder != nil){
            nextResponder?.becomeFirstResponder()

        }
        return false;


    }else if (textField.text?.count)! >= 1 && string.count == 0 {
        let prevTag = textField.tag - 1
        let prevResponser = textField.superview?.viewWithTag(prevTag)
          if (prevResponser != nil){
            textField.resignFirstResponder()
        }
        textField.text = string
        if (prevResponser != nil){
            prevResponser?.becomeFirstResponder()

        }
         return false
    }


    return true;

}
Yashmak answered 13/7, 2018 at 9:11 Comment(1)
@ElTomato now i will added swift4.2 code check once.Yashmak
E
1

Here I was take 4 TextField

@IBOutlet var txtOtp: [BottomBorderTextField]!

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

    defer{
        if !string.isEmpty {
            textField.text = string
            textField.resignFirstResponder()
            if let index = self.txtOtp.index(where:{$0 === textField}) {
                if index < 3 {
                  self.txtOtp[index + 1].becomeFirstResponder()
                }
            }
        }
    }
    return true
}
Escargot answered 15/3, 2019 at 5:21 Comment(0)
A
1

let do something different using IQKeyboardManager.It work like charm. Do not forget set delegate for every text field.

//MARK:- TextField delegate methods
@objc func textFieldDidChange(textField: UITextField){

    if textField.text!.count == 1{
        if IQKeyboardManager.shared().canGoNext{
            IQKeyboardManager.shared().goNext()
        }
    }else{
        if IQKeyboardManager.shared().canGoPrevious{
            IQKeyboardManager.shared().goPrevious()
        }
    }
}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if string == " "{
        return false
    }else if string.isEmpty{
        return true
    }else if textField.text!.count == 1{
        textField.text = string
        if IQKeyboardManager.shared().canGoNext{
            IQKeyboardManager.shared().goNext()
        }
        return false
    }
    return true
}
Achromatic answered 22/1, 2020 at 13:6 Comment(0)
I
0

**call from UITextfieldDelegate function and make next text field the first responder and no need to add target and remember to set delegates of all text fields in viewDidLoad **

            extension ViewController : UITextFieldDelegate {


            func textFieldShouldReturn(textField: UITextField) -> Bool {

              nextTextFieldToFirstResponder(textField)

              return true;
            }




          func nextTextFieldToFirstResponder(textField: UITextField) {

            if textField == emailTextField
            {
              self.firstNameTextField.becomeFirstResponder()
            }
            else if   textField == firstNameTextField {

              self.lastNameTextField.becomeFirstResponder()
            }

            else if  textField == lastNameTextField {

              self.passwordTextField.becomeFirstResponder()
            }

            else if textField == passwordTextField {

              self.confirmPassTextField.becomeFirstResponder()
            }

            else if textField == confirmPassTextField {
              self.confirmPassTextField.resignFirstResponder()

            }

          }
Iceboat answered 11/2, 2016 at 11:30 Comment(0)
C
0

I have tried many codes and finally this worked for me in Swift 3.0 Latest [March 2017]

The "ViewController" class should inherited the "UITextFieldDelegate" for making this code working.

class ViewController: UIViewController,UITextFieldDelegate 

Add the Text field with the Proper Tag nuber and this tag number is used to take the control to appropriate text field based on incremental tag number assigned to it.

override func viewDidLoad() {

 userNameTextField.delegate = self

        userNameTextField.tag = 0

        userNameTextField.returnKeyType = UIReturnKeyType.next

        passwordTextField.delegate = self

        passwordTextField.tag = 1


        passwordTextField.returnKeyType = UIReturnKeyType.go

}

In the above code, the "returnKeyType = UIReturnKeyType.next" where will make the Key pad return key to display as "Next" you also have other options as "Join/Go" etc, based on your application change the values.

This "textFieldShouldReturn" is a method of UITextFieldDelegate controlled and here we have next field selection based on the Tag value incrementation

func textFieldShouldReturn(_ textField: UITextField) -> Bool

    {

        if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {

            nextField.becomeFirstResponder()

        } else {

            textField.resignFirstResponder()

            return true;

        }

        return false

    }
Custom answered 22/3, 2017 at 17:23 Comment(0)
L
0

Use textFieldShouldBeginEditing method

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
   scrlView.setContentOffset(CGPointMake(0, textField.frame.origin.y-70), 
 animated:true)

   if(textField == firstDigit){

      textField.becomeFirstResponder()
     secondDigit.resignFirstResponder()
   }
   else if(textField == secondDigit){

    textField.becomeFirstResponder()
    thirdDigit.resignFirstResponder()
    }
    else if(textField == thirdDigit){
    //textField.becomeFirstResponder()
    fourthDigit.becomeFirstResponder()
    }
   return true;
}
Lurie answered 26/6, 2018 at 7:51 Comment(0)
G
0
//MARK:- IBOutlets    
    @IBOutlet weak var tfFirstDigit: UITextField!
    @IBOutlet weak var tfSecondDigit: UITextField!
    @IBOutlet weak var tfThirdDigit: UITextField!
    @IBOutlet weak var tfFourthDigit: UITextField!

//MARK:- view Life Cycle

    override func viewDidLoad() {
        super.viewDidLoad()

        tfFirstDigit.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
        tfSecondDigit.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
        tfThirdDigit.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
        tfFourthDigit.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)



    }

 //MARK:- Text Field Delegate methods
    @objc func textFieldDidChange(textField: UITextField){
        let text = textField.text

        if (text?.utf16.count)! >= 1{
            switch textField{
            case tfFirstDigit:
                tfSecondDigit.becomeFirstResponder()
            case tfSecondDigit:
                tfThirdDigit.becomeFirstResponder()
            case tfThirdDigit:
                tfFourthDigit.becomeFirstResponder()
            case tfFourthDigit:
                tfFourthDigit.resignFirstResponder()
            default:
                break
            }
        }else{

        }
    }



    func textFieldDidBeginEditing(_ textField: UITextField) {
        textField.text = ""
    }
Goon answered 18/12, 2019 at 9:42 Comment(0)
E
-1

for swift 3

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    // On inputing value to textfield
    if ((textField.text?.characters.count)! < 1  && string.characters.count > 0){
        let nextTag = textField.tag + 1;

        // get next responder
        let nextResponder = textField.superview?.viewWithTag(nextTag);
        textField.text = string;

        if (nextResponder == nil){
            textField.resignFirstResponder()
        }
        nextResponder?.becomeFirstResponder();
        return false;
    }
    else if ((textField.text?.characters.count)! >= 1  && string.characters.count == 0){
        // on deleting value from Textfield
        let previousTag = textField.tag - 1;

        // get next responder
        var previousResponder = textField.superview?.viewWithTag(previousTag);

        if (previousResponder == nil){
            previousResponder = textField.superview?.viewWithTag(1);
        }
        textField.text = "";
        previousResponder?.becomeFirstResponder();
        return false;
    }
    return true;
}
Euratom answered 6/6, 2017 at 12:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.