如果我们使用多个文本字段,如何自动获取OTP

amm*_*eja 8 one-time-password uitextfield ios swift

我知道,如果要自动获取OTP(如果使用单个文本字段),则需要使用

otpTextField.textContentType = .oneTimeCode
Run Code Online (Sandbox Code Playgroud)

但是,如果我们使用多个文本字段(根据下图)

像这样的东西

我们应该如何实现呢?

Him*_*tel 7

-> 从 iOS 12 开始,Apple 将支持读取您将在 iPhone 设备中获得的一次性代码。您可以将文本分成四个字段并自动填充并手动输入 otp 并一一删除并移动每个文本字段。

1) self.textone 最大长度 4 和其他文本字段最大长度 1

2) 添加 UITextFieldDelegate

在此处输入图片说明

if #available(iOS 12.0, *) {
   txtOne.textContentType = .oneTimeCode
}
self.txtOne.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
self.txtOne.becomeFirstResponder()

  @objc func textFieldDidChange(_ textField: UITextField) {
    if #available(iOS 12.0, *) {
        if textField.textContentType == UITextContentType.oneTimeCode{
            //here split the text to your four text fields
            if let otpCode = textField.text, otpCode.count > 3{
                txtOne.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 0)])
                txtTwo.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 1)])
                txtThree.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 2)])
                txtFour.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 3)])
            }
        }
     } 
  }

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

       if (string.count == 1){
           if textField == txtOne {
               txtTwo?.becomeFirstResponder()
           }
           if textField == txtTwo {
               txtThree?.becomeFirstResponder()
           }
           if textField == txtThree {
               txtFour?.becomeFirstResponder()
           }
           if textField == txtFour {
               txtFour?.resignFirstResponder()
               textField.text? = string
                //APICall Verify OTP
               //Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(self.VerifyOTPAPI), userInfo: nil, repeats: false)
           }
           textField.text? = string
           return false
       }else{
           if textField == txtOne {
               txtOne?.becomeFirstResponder()
           }
           if textField == txtTwo {
               txtOne?.becomeFirstResponder()
           }
           if textField == txtThree {
               txtTwo?.becomeFirstResponder()
           }
           if textField == txtFour {
               txtThree?.becomeFirstResponder()
           }
           textField.text? = string
           return false
       }

   }
Run Code Online (Sandbox Code Playgroud)


Jua*_*los 6

我在 6 个不同的 UITextFields 中使用 Firebase OneTimeCode 并设法允许操作系统从文本消息自动填充它,还允许用户复制和粘贴它,当然允许用户通过实现 shouldChangeCharactersIn 在一个非常手动但有效的方法:

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

        //This lines allows the user to delete the number in the textfield.
        if string.isEmpty{
            return true
        }
        //----------------------------------------------------------------

        //This lines prevents the users from entering any type of text.
        if Int(string) == nil {
            return false
        }
        //----------------------------------------------------------------

        //This lines lets the user copy and paste the One Time Code.
        //For this code to work you need to enable subscript in Strings https://gist.github.com/JCTec/6f6bafba57373f7385619380046822a0
        if string.count == 6 {
            first.text = "\(string[0])"
            second.text = "\(string[1])"
            third.text = "\(string[2])"
            fourth.text = "\(string[3])"
            fifth.text = "\(string[4])"
            sixth.text = "\(string[5])"

            DispatchQueue.main.async {
                self.dismissKeyboard()
                self.validCode()
            }
        }
        //----------------------------------------------------------------

        //This is where the magic happens. The OS will try to insert manually the code number by number, this lines will insert all the numbers one by one in each TextField as it goes In. (The first one will go in normally and the next to follow will be inserted manually)
        if string.count == 1 {
            if (textField.text?.count ?? 0) == 1 && textField.tag == 0{
                if (second.text?.count ?? 0) == 1{
                    if (third.text?.count ?? 0) == 1{
                        if (fourth.text?.count ?? 0) == 1{
                            if (fifth.text?.count ?? 0) == 1{
                                sixth.text = string
                                DispatchQueue.main.async {
                                    self.dismissKeyboard()
                                    self.validCode()
                                }
                                return false
                            }else{
                                fifth.text = string
                                return false
                            }
                        }else{
                            fourth.text = string
                            return false
                        }
                    }else{
                        third.text = string
                        return false
                    }
                }else{
                    second.text = string
                    return false
                }
            }
        }
        //----------------------------------------------------------------


        //This lines of code will ensure you can only insert one number in each UITextField and change the user to next UITextField when function ends.
        guard let textFieldText = textField.text,
            let rangeOfTextToReplace = Range(range, in: textFieldText) else {
                return false
        }
        let substringToReplace = textFieldText[rangeOfTextToReplace]
        let count = textFieldText.count - substringToReplace.count + string.count


        if count == 1{
            if textField.tag == 0{
                DispatchQueue.main.async {
                    self.second.becomeFirstResponder()
                }

            }else if textField.tag == 1{
                DispatchQueue.main.async {
                    self.third.becomeFirstResponder()
                }

            }else if textField.tag == 2{
                DispatchQueue.main.async {
                    self.fourth.becomeFirstResponder()
                }

            }else if textField.tag == 3{
                DispatchQueue.main.async {
                    self.fifth.becomeFirstResponder()
                }

            }else if textField.tag == 4{
                DispatchQueue.main.async {
                    self.sixth.becomeFirstResponder()
                }

            }else {
                DispatchQueue.main.async {
                    self.dismissKeyboard()
                    self.validCode()
                }
            }
        }

        return count <= 1
        //----------------------------------------------------------------

    }
Run Code Online (Sandbox Code Playgroud)

注意:我在这段代码中使用了下标字符串方法,你可以在这里获取这个扩展名,String+Subscript.swift

当然不要忘记将委托和 .oneTimeCode 分配给 TextField。

textField.delegate = self
textField.textContentType = .oneTimeCode
Run Code Online (Sandbox Code Playgroud)


Nat*_*jan 4

如果您可以获得单个字段的自动 OTP,则可以将该文本拆分为四个文本字段。我相信。

您可能必须使用 textField 的更改观察器,如下所示,

textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
func textFieldDidChange(_ textField: UITextField) {

        // here check you text field's input Type
        if textField.textContentType == UITextContentType.oneTimeCode{

            //here split the text to your four text fields

            if let otpCode = textField.text, otpCode.count > 3{

                textField.text = String(otpCode[otpCode.startIndex])
                textField1.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 1)])
                textField2.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 2)])
                textField3.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 3)])
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这是行不通的。由于当我单击键盘上的 OTP 建议时,textField.text 给出了空文本。 (5认同)