How to auto fetch OTP, if we use multiple text fields

后端 未结 4 1380
花落未央
花落未央 2021-01-07 23:52

I know that if we want to auto fetch the OTP(if we use single textfield) we need to use

otpTextField.textContentType = .oneTimeCode

But, If

4条回答
  •  情书的邮戳
    2021-01-08 00:36

    I was stuck with Firebase OneTimeCode in 6 different UITextFields and manage to allow the OS to autofill it from Text Message, also to allow the user to copy and paste it and of course to allow the user to insert it one by one by implementing shouldChangeCharactersIn in a very manual but effective way:

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

    Note: I use a subscript string method in this code, you can get this extension here, String+Subscript.swift

    And of course don't forget to assign the delegate and the .oneTimeCode to the TextField.

    textField.delegate = self
    textField.textContentType = .oneTimeCode
    

提交回复
热议问题