IOS – Handle OnetimeCode in Swift

Viewed 8675

Is there any way to handle onetime-code tap by restricting other keyboard entries?

I have requirement for an OTP text field to prefill the sms OTP code. User should not enter the OTP manually using keyboard numeric buttons.

IOS 12 we have the onetime-code option, it will be auto-filled in QuickType bar & User can tap on it to fill the text field. I Couldn't find an option to restrict other keyboard entries.

Is there any way we can allow only Onetime code tap and restricting any entry from the numeric keyboard .

What I have tried is created 6 textfields. First textfield content type set as One Time code. UserInteractionEnabled only for the first text field so that user can't enter data onto other fields. Once I get the OTP & taps QuickType bar - onetime code, I am prefilling all the text fields.

viewdidload>

otp1TB.addTarget(self, action:#selector(textFieldDidChange(_:)), for: .editingChanged)


@objc func textFieldDidChange(_ textField: UITextField) {
    if let otpCode = textField.text ,  otpCode.count > 5 {
        otp1TB.text = String(otpCode[otpCode.startIndex])
        otp2TB.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 1)])
        otp3TB.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 2)])
        otp4TB.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 3)])
        otp5TB.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 4)])
        otp6TB.text = String(otpCode[otpCode.index(otpCode.startIndex, offsetBy: 5)])
        otp1TB.isUserInteractionEnabled = false 
        self.view.endEditing(true)
    }
}

The issue here is since the first text field is active when the keyboard opens user has the ability to enter numeric data from the keyboard.

I need to allow only onetime code tap when the keyboard opens.

2 Answers

You can try My 3rd party library:- https://github.com/Datt1994/DPOTPView

For Solution:-

In viewDidLoad add tag & delegate to all textfield

override func viewDidLoad() {
    super.viewDidLoad()
    otp1TB.delegate = self
    otp1TB.tag = 1000
    otp2TB.delegate = self
    otp2TB.tag = 2000
    otp3TB.delegate = self
    otp3TB.tag = 3000
    otp4TB.delegate = self
    otp4TB.tag = 4000
    otp5TB.delegate = self
    otp5TB.tag = 5000
    otp6TB.delegate = self
    otp6TB.tag = 6000
}

In UITextFieldDelegate extension implement shouldChangeCharactersIn function like below, It will also work with textField.textContentType = .oneTimeCode

extension ViewController : 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
}

}
Related