首页 > 解决方案 > 带有六个单字符文本字段的 OTP 输入表单

问题描述

我正在开发一个应用程序,在该应用程序中,我必须通过 6 个文本字段传递 6 位 OTP,在其中您只提供一个字符,然后它会自动转到另一个文本字段。我创建了 6 个 textFields 插座并使用了这段代码。我遇到的问题是我想更改特定的textFieldOTP 编号,但问题是如果我想在点击十字按钮后更改文本字段 4 的 OTP 编号,它会自动转到文本字段 3。我该如何解决这个问题?

我使用的代码:

import UIKit

class OneTimePasswordViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var txtOTP1: UITextField!
    @IBOutlet weak var txtOTP2: UITextField!
    @IBOutlet weak var txtOTP3: UITextField!
    @IBOutlet weak var txtOTP4: UITextField!
    @IBOutlet weak var txtOTP5: UITextField!
    @IBOutlet weak var txtOTP6: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        txtOTP1.delegate = self
        txtOTP2.delegate = self
        txtOTP3.delegate = self
        txtOTP4.delegate = self
        txtOTP5.delegate = self
        txtOTP6.delegate = self

       self.txtOTP1.becomeFirstResponder()
    }
}

这是创建逻辑的代码:

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

    if (range.length == 0){
        if textField == txtOTP1 {txtOTP2?.becomeFirstResponder()}
        if textField == txtOTP2 {txtOTP3?.becomeFirstResponder()}
        if textField == txtOTP3 {txtOTP4?.becomeFirstResponder()}
        if textField == txtOTP4 {txtOTP5?.becomeFirstResponder()}
        if textField == txtOTP5 {txtOTP6?.becomeFirstResponder()}
        if textField == txtOTP6 {txtOTP6?.resignFirstResponder()}
        textField.text? = string
        return false
    }
    else if (range.length == 1) {

        if textField == txtOTP6 {txtOTP5?.becomeFirstResponder()}
        if textField == txtOTP5 {txtOTP4?.becomeFirstResponder()}
        if textField == txtOTP4 {txtOTP3?.becomeFirstResponder()}
        if textField == txtOTP3 {txtOTP2?.becomeFirstResponder()}
        if textField == txtOTP2 {txtOTP1?.becomeFirstResponder()}
        if textField == txtOTP1 {txtOTP1?.resignFirstResponder()}

        textField.text? = ""
        return false
    }
    return true
}

标签: iosswiftuitextfield

解决方案


您可以尝试我的 3rd 方库:- https://github.com/Datt1994/DPOTPView

对于解决方案: -

在 viewDidLoad 添加标签和委托给所有textfield

import UIKit

class OneTimePasswordViewController: UIViewController, UITextFieldDelegate {

     @IBOutlet weak var txtOTP1: UITextField!
     @IBOutlet weak var txtOTP2: UITextField!
     @IBOutlet weak var txtOTP3: UITextField!
     @IBOutlet weak var txtOTP4: UITextField!
     @IBOutlet weak var txtOTP5: UITextField!
     @IBOutlet weak var txtOTP6: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        txtOTP1.delegate = self
        txtOTP1.tag = 1000
        txtOTP2.delegate = self
        txtOTP2.tag = 2000
        txtOTP3.delegate = self
        txtOTP3.tag = 3000
        txtOTP4.delegate = self
        txtOTP4.tag = 4000
        txtOTP5.delegate = self
        txtOTP5.tag = 5000
        txtOTP6.delegate = self
        txtOTP6.tag = 6000

       self.txtOTP1.becomeFirstResponder()
   }
}

在 UITextFieldDelegate 扩展实现shouldChangeCharactersIn功能如下所示,它也将与textField.textContentType = .oneTimeCode

extension OneTimePasswordViewController : UITextFieldDelegate  {

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if string.trimmingCharacters(in: CharacterSet.whitespaces).count != 0 {
        textField.text = string
        if textField.tag < count*1000 {
            let next = textField.superview?.viewWithTag((textField.tag/1000 + 1)*1000)
            next?.becomeFirstResponder()
        } else if textField.tag == count*1000 {
            textField.resignFirstResponder()
        }
    } else if string.count == 0 { // is backspace
        textField.text = ""
    }

    return false
}

}

推荐阅读