4

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.

brandonscript
  • 68,675
  • 32
  • 163
  • 220
SJMC
  • 95
  • 2
  • 3
  • 10

2 Answers2

2

I think you can skip this entire complexity and just use the standard iOS 12 OTP input type:

otpTextField.textContentType = .oneTimeCode

See: Automatic OTP verification in iOS?

And the WWDC 2018 video that covers it: https://developer.apple.com/videos/play/wwdc2018/204

brandonscript
  • 68,675
  • 32
  • 163
  • 220
  • First text field content type set as One Time Code in storyboard. I am looking for a solution to restrict other keyboard numeric entry. – SJMC Jun 21 '19 at 06:07
  • Sorry, that wasn't very clear in your question - it was hard to follow. Sounds like you want this: https://stackoverflow.com/a/53414345/1214800 – brandonscript Jun 21 '19 at 06:08
  • I have tried that. No luck with statement "if textField.textContentType == UITextContentType.oneTimeCode" – SJMC Jun 21 '19 at 06:13
  • OK, then I would suggest rewording your question to make it clear what the problem is you're having, and explain how it relates to the code you've shown. – brandonscript Jun 21 '19 at 06:15
  • Sorry, if it was not clear. I have updated the text – SJMC Jun 21 '19 at 10:20
1

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
}

}
Datt Patel
  • 1,203
  • 1
  • 11
  • 10