Как автоматически перемещать курсор из одного текстового поля в другое в Swift ios программно?

    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()
    }

Я использую четыре текстовых поля для ввода одноразового пароля, в которые можно вводить только одно число. После ввода числа мне нужно автоматически переместить курсор в следующее текстовое поле.


person Rakesh Mohan    schedule 11.02.2016    source источник
comment
github.com/hackiftekhar/IQKeyboardManager Добавьте эту библиотеку в свой проект с помощью модулей и готово. Вам не нужно ничего кодировать или добавлять что-то еще. Эта библиотека управляет всем сама.   -  person aBilal17    schedule 26.06.2018
comment
см. это для справки: stackoverflow.com/questions/53665104/otp- textfields-swift /   -  person Anbu.Karthik    schedule 07.12.2018
comment
Попробуйте это: - github.com/Datt1994/DPOTPView   -  person Datt Patel    schedule 13.05.2020


Ответы (12)


Установите делегат textField и добавьте цель:

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)
    }

Теперь при изменении текста измените 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{

    }
}

И, наконец, когда пользователь начинает редактировать текстовое поле

extension ViewController: UITextFieldDelegate{
    func textFieldDidBeginEditing(textField: UITextField) {
        textField.text = ""
    }
}
person Hamza Ansari    schedule 11.02.2016
comment
Если мы хотим автоматически получить OTP (если мы используем одно текстовое поле), нам нужно использовать otpTextField.textContentType = .oneTimeCode, если мы используем несколько текстовых файлов, как мы должны этого добиться? - person Bhanuteja; 21.11.2018
comment
Swift 4.2 didBeginEditing был изменен на: func textFieldDidBeginEditing (_ textField: UITextField) {textField.text =} - person Lance Samaria; 08.02.2019

обновить решение для Swift 5

В этом решении вы перейдете к следующему полю. И когда вы нажмете «Стереть», вы перейдете в предыдущее текстовое поле.

Шаг 1. Установите селектор для текстового поля.

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)
        
    }

Шаг 2: Теперь мы займемся перемещением следующего текстового поля и стиранием текстового поля.

@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{

        }
    }

Важное примечание: не забудьте установить делегат.

person Anup Gupta    schedule 07.03.2018
comment
добавить otpTextField * .selectAll (nil) для автоматического выбора текста - person Rohit Funde; 11.03.2019
comment
Большое спасибо за такой плодотворный ответ! - person Neeraj Shukla; 09.09.2019
comment
После стирания мы не можем перейти к следующему текстовому полю, пока не нажмем вручную - person Abhinav Jha; 04.05.2020
comment
@AbhinavJha проверить текст? .Count == 0 звонит на Erase Press.? - person Anup Gupta; 04.05.2020
comment
@AbhinavJha Вы установили делегата? - person Anup Gupta; 04.05.2020

Код Swift 3 для автоматического перемещения курсора из одного поля в другое в полях OTP (одноразовый пароль).

    //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
    }
person santhosh kumar    schedule 04.07.2018

Это похоже на то, как UberEats имеет свои поля otp. Вы можете просто скопировать и вставить это в файл и запустить, чтобы посмотреть, как это работает. Но не забудьте добавить класс MyTextField, иначе он не сработает.

Если вы хотите, чтобы он автоматически переходил к следующему текстовому полю после ввода числа и по-прежнему имел возможность перемещаться назад, если нажата кнопка «Назад», пока текстовое поле пусто, это поможет вам.

Как и самое первое, что я сказал, это похоже на то, как в UberEats работают текстовые поля sms. Вы не можете просто случайным образом нажать на текстовое поле и выбрать его. Используя это, вы можете двигаться только вперед и назад. UX субъективен, но если Uber использует его, UX должен быть действительным. Я говорю, что это похоже, потому что у них также есть серый прямоугольник, закрывающий textField, поэтому я не уверен, что за ним происходит. Это было самое близкое, что я мог найти.

Сначала вам нужно будет создать подкласс UITextField , используя этот ответ, чтобы определить, когда нажата кнопка возврата. Когда нажата кнопка «Назад», вы стираете все внутри этого поля И в предыдущем поле, а затем переходите к предыдущему полю.

Во-вторых, вам придется запретить пользователю выбирать левую сторону курсора, когда символ находится внутри текстового поля , используя этот ответ. Вы переопределяете метод в том же подклассе из первого шага.

В-третьих, вам нужно определить, какое текстовое поле в настоящее время активно , используя этот ответ

В-четвертых, вам нужно будет выполнить несколько проверок внутри func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool с помощью этого руководства YouTube. Я кое-что добавил к его работам.

Я все делаю программно, чтобы вы могли скопировать и вставить весь код в проект и запустить его

Сначала создайте подкласс UITextField и назовите его 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
    }
}

Во-вторых, внутри класса с текстовыми полями OTP настройте класс на использование UITextFieldDelegate и MyTextFieldDelegate, затем создайте свойство класса и назовите его activeTextField. Когда любое текстовое поле становится активным внутри textFieldDidBeginEditing, вы устанавливаете activeTextField на это. В viewDidLoad установите все текстовые поля для использования обоих делегатов.

Убедитесь, что для первого поля otpTextField установлено значение ВКЛЮЧЕНО, а для второго, третьего и четвертого полей otpTextField изначально задано значение 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
     }
}

введите описание изображения здесь

Это отдельно от ответа выше, но если вам нужно добавить несколько символов в каждое поле otpTextField, тогда следуйте этому ответу < / а>.

person Lance Samaria    schedule 08.02.2019
comment
Я хочу, чтобы первое текстовое поле отображало 3 символа, второе - 4, третье - 7 и четвертое текстовое поле - 1 символ. как я могу этого добиться? пожалуйста помоги - person Syed Faraz Haider Zaidi; 11.03.2019
comment
где я должен это добавить. не могли бы вы объяснить, или мне следует открыть новый вопрос, и вы сможете ответить там? - person Syed Faraz Haider Zaidi; 11.03.2019
comment
Задайте новый вопрос - person Lance Samaria; 11.03.2019
comment
Я посмотрю позже - person Lance Samaria; 11.03.2019

Сначала нам нужно установить тег для 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
}

Примечание. UITextField принимает только один символ в числовом формате, то есть в формате OTP.

person Priyanka Jadhav    schedule 16.05.2017

Цель c и Swift 4.2 для автоматического перемещения курсора из одного поля в другое в полях OTP (одноразовый пароль)

Здесь я беру один контроллер представления  просмотреть стек дизайна экрана контроллера внутри текстовых файлов [! [] [1] ] 1

Затем укажите значения тегов для каждого TextFiled. Соответствующие справочные изображения показаны ниже  Введите значение тега для первого сохраненного текстового файла - ›1,2ndTextfiled ----› 2,3rd TextFiled --- ›3 4rth TextFiled ----  ›4

введите описание изображения здесь

Введите значение тега для первого текстового файла -> 1,2ndTextfiled ----> 2,3rd TextFiled ---> 3 4rth TextFiled ----> 4

Затем назначьте делегатов с текстовым файлом и напишите код ниже и увидите волшебство

 - (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

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;

}
person Gangireddy Rami Reddy    schedule 13.07.2018
comment
@ElTomato теперь я добавлю проверку кода swift4.2 один раз. - person Gangireddy Rami Reddy; 12.03.2019

** вызовите из функции UITextfieldDelegate и сделайте следующее текстовое поле первым респондентом и не нужно добавлять цель и не забудьте установить делегатов всех текстовых полей в 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()

            }

          }
person Ajay Singh Thakur    schedule 11.02.2016

Я перепробовал много кодов, и, наконец, у меня это сработало в Swift 3.0. Последняя версия [март 2017 г.]

Класс «ViewController» должен унаследовать «UITextFieldDelegate», чтобы этот код работал.

class ViewController: UIViewController,UITextFieldDelegate 

Добавьте текстовое поле с правильным номером тега, и этот номер тега используется для переноса управления в соответствующее текстовое поле на основе присвоенного ему инкрементного номера тега.

override func viewDidLoad() {

 userNameTextField.delegate = self

        userNameTextField.tag = 0

        userNameTextField.returnKeyType = UIReturnKeyType.next

        passwordTextField.delegate = self

        passwordTextField.tag = 1


        passwordTextField.returnKeyType = UIReturnKeyType.go

}

В приведенном выше коде «returnKeyType = UIReturnKeyType.next», где клавиша возврата клавиатуры будет отображаться как «Далее», у вас также есть другие параметры, такие как «Присоединиться / Перейти» и т. Д., В зависимости от изменения значений вашего приложения.

Этот "textFieldShouldReturn" является методом управляемого UITextFieldDelegate, и здесь у нас есть следующий выбор поля на основе увеличения значения тега

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

    }
person BHUVANESH MOHANKUMAR    schedule 22.03.2017

Используйте метод textFieldShouldBeginEditing

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;
}
person Sureshkumar Linganathan    schedule 26.06.2018

Здесь я взял 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
}
person Arjun Patel    schedule 15.03.2019

позвольте сделать что-нибудь другое с помощью IQKeyboardManager. Это работает как шарм. Не забудьте установить делегата для каждого текстового поля.

//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
}
person seggy    schedule 22.01.2020

для 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;
}
person Sachin Nautiyal    schedule 06.06.2017