Auto Resign and assign first responder in text fie

2019-06-11 09:25发布

I have taken 3 text fields and want them to hold just one integer for OTP purpose (It's the need of the project design). When user enters number in first textfield, the responder should automatically get assigned to the second text field and then to the third text field. As soon as user enters last OTP digit in the third textfield, I want to hit the webservice. What I did so far is :

class ActivationCodeVC: UIViewController, UITextFieldDelegate

then

otpField1.delegate = self
otpField2.delegate = self
otpField3.delegate = self

then

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

    let text=textField.text
    let counter = text?.characters.count
    if counter >= 1 {

        if textField == otpField1{

            otpField2.becomeFirstResponder()

        } else if textField == otpField2{

            otpField3.becomeFirstResponder()

        } else if textField == otpField3{

            otpField3.resignFirstResponder()

        }

    }

    return true
}

Cursor should start blinking on the 2nd textfield when user enters digit in the 1st textfield. But it doesn't. After I press the second digit, it enters it to the second textfield and then again cursor doesn't moves to the third, but remains in the second text field. Secondly, when I try to remove digit by backspace, say for, when I try removing 1st textfield digit, it removes digit from the second textfield.

Please help me what methods I should implement and how to achieve the functionality correctly.

I tried this but character is printing in the second text field instead of first and so on.

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

    let text = textField.text
    // create Range<Index> object from old-style one
    let start = text!.startIndex.advancedBy(range.location)
    let end = start.advancedBy(range.length)
    let indexRange = start..<end
    // calculate result string value
    let result = text!.stringByReplacingCharactersInRange(indexRange, withString: string)

//        let text=textField.text
    let tempCount = result.characters.count
    if tempCount == 1 {

        if textField == otpField1{

            otpField2.becomeFirstResponder()

        } else if textField == otpField2{

            otpField3.becomeFirstResponder()

        } else if textField == otpField3{

            otpField3.resignFirstResponder()

            let tempCode = otpField1.text! + otpField2.text! + otpField3.text!

            if  !APPDELEGATE.internetStatusFalse {
                KVNProgress.showWithStatus("Loading...")
                let soapApiObj: SoapApi = SoapApi()
                mode = ControllerTypeMode.ACTIVAITONCODE
                soapApiObj.resDelegate = self
                soapApiObj.responseString = NSMutableString(string: "")
                soapApiObj.callActivationCodeApi(tempCode)
            }
            else{
                let obj: SuccessFullPopVC=self.storyboard?.instantiateViewControllerWithIdentifier("successFullPopVC") as! SuccessFullPopVC
                obj.titlelbl = LocalizationSystem.sharedLocalSystem().localizedStringForKey("Warning", value: nil)
                obj.imgSuccess = UIImage(named: "warning")
                obj.messagelbl = LocalizationSystem.sharedLocalSystem().localizedStringForKey("No internet connection.", value: nil)
                self.navigationController?.presentViewController(obj, animated: false, completion: nil)
            }

        }

    }

    return true
}

Thanks for the final solution:

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

    let text = textField.text
    // create Range<Index> object from old-style one
    let start = text!.startIndex.advancedBy(range.location)
    let end = start.advancedBy(range.length)
    let indexRange = start..<end
    // calculate result string value
    let result = text!.stringByReplacingCharactersInRange(indexRange, withString: string)

    let newLength = result.characters.count

    if textField == otpField1{
        if newLength == 1 {
            otpField1.text = result
            otpField2.becomeFirstResponder()
            return false
        }

    } else if textField == otpField2{
        if newLength == 1 {
            otpField2.text = result
            otpField3.becomeFirstResponder()
            return false
        }

    } else if textField == otpField3{
        if newLength == 1 {
            otpField3.text = result
            return false

        }

    }

    return !(result.characters.count>1)
}

It Works!!

2条回答
我命由我不由天
2楼-- · 2019-06-11 10:07

The shouldChangeCharactersInRange-delegate method get called before the actual text change (character put/delete in your case).

Firstly, calculate string you'll obtain after the input action. Use delegate method arguments (range, string) and textField.text like in a snippet below.

let text = textField.text
// create Range<Index> object from old-style one
let start = text.startIndex.advancedBy(range.location)
let end = start.advancedBy(range.length)
let indexRange = start..<end
// calculate result string value
let result = text.stringByReplacingCharactersInRange(indexRange, withString: string)
查看更多
我命由我不由天
3楼-- · 2019-06-11 10:13

Updated for Swift 3:

Used below simple code:

//To asssing next responder
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if (textField == self.nameTextField) {
        self.textField = self.emailTextField
        self.emailTextField.becomeFirstResponder()
    } else if (textField == self.emailTextField) {
        self.textField = self.phoneNumberTextfield
        self.phoneNumberTextfield.becomeFirstResponder()
    } else if(textField == self.phoneNumberTextfield) {
        self.textField = self.amountTextField
        self.amountTextField.becomeFirstResponder()
    } else if (textField == self.amountTextField) {
        self.textField = self.descriptionTextField
        self.descriptionTextField.becomeFirstResponder()
    } else {
        textField.resignFirstResponder()
    }
    return false
}
查看更多
登录 后发表回答