0

I am building an iOS app which requires user to input pin which consists of 4 digits. So, I created 4 TextField separately in order to accept one number for each TextField. It is working fine when user inputs each textfield and move forward from textfield to another textfield smoothly.

But the problem is that I want user be able to delete by clicking on clear button icon that provided by iOS built-in keyboard. When user clicks on that icon button it should let textfield move to previous textfield but it does not work for me.

I have found lots of resources online on stackoverflow and it is still not working for me. That is why I created my own question.

This is how my code looks likes! I created textfield programmatically!

self.coverView.addSubview(self.paymentView.firstDigit)
self.coverView.addSubview(self.paymentView.secondDigit)
self.coverView.addSubview(self.paymentView.thirdDigit)
self.coverView.addSubview(self.paymentView.fourthDigit)

self.view.addSubview(self.overlayView)
self.overlayView.snp.makeConstraints { (make) in
    make.top.width.height.centerX.equalTo(self.coverView)
}
self.paymentView.firstDigit.becomeFirstResponder()


self.paymentView.firstDigit.snp.makeConstraints { (make) in
    make.top.equalTo(self.coverView)
    make.width.height.equalTo(21)
    make.leading.equalTo(self.coverView)
}
self.paymentView.secondDigit.snp.makeConstraints { (make) in
    make.top.equalTo(self.coverView)
    make.leading.equalTo(self.paymentView.firstDigit.snp.trailing).offset(8)
    make.width.height.equalTo(21)
}
self.paymentView.thirdDigit.snp.makeConstraints { (make) in
    make.top.equalTo(self.coverView)
    make.leading.equalTo(self.paymentView.secondDigit.snp.trailing).offset(8)
    make.width.height.equalTo(21)
}
self.paymentView.fourthDigit.snp.makeConstraints { (make) in
   make.top.equalTo(self.coverView)
    make.leading.equalTo(self.paymentView.thirdDigit.snp.trailing).offset(8)
    make.width.height.equalTo(21)
}

self.paymentView.firstDigit.delegate = self
self.paymentView.secondDigit.delegate = self
self.paymentView.thirdDigit.delegate = self
self.paymentView.fourthDigit.delegate = self 

The code above included delegate of TextField. And below is how I setup target for each TextField

self.paymentView.firstDigit.addTarget(self, action: #selector(textfieldDidChange(textField:)), for: .editingChanged)
self.paymentView.secondDigit.addTarget(self, action: #selector(textfieldDidChange(textField:)), for: .editingChanged)
self.paymentView.thirdDigit.addTarget(self, action: #selector(textfieldDidChange(textField:)), for: .editingChanged)
self.paymentView.fourthDigit.addTarget(self, action: #selector(textfieldDidChange(textField:)), for: .editingChanged)

And below is the function of textfieldDidChange

 @objc func textfieldDidChange(textField: UITextField) {
        let text = textField.text
        print("This is an amount of text ", text?.count)
        if text?.count == 1 {
            switch textField {
            case self.paymentView.firstDigit:
                self.paymentView.firstDigit.textColor = BaseColor.colorPrimary
                self.paymentView.firstDigit.backgroundColor = BaseColor.colorPrimary
                self.paymentView.secondDigit.becomeFirstResponder()

            case self.paymentView.secondDigit:
                self.paymentView.secondDigit.textColor = BaseColor.colorPrimary
                self.paymentView.thirdDigit.becomeFirstResponder()
                self.paymentView.secondDigit.backgroundColor = BaseColor.colorPrimary

            case self.paymentView.thirdDigit:
                self.paymentView.thirdDigit.textColor = BaseColor.colorPrimary
                self.paymentView.fourthDigit.becomeFirstResponder()
                self.paymentView.thirdDigit.backgroundColor = BaseColor.colorPrimary

            case self.paymentView.fourthDigit:
                self.paymentView.fourthDigit.textColor = BaseColor.colorPrimary
                self.paymentView.fourthDigit.backgroundColor = BaseColor.colorPrimary
                self.paymentView.fourthDigit.resignFirstResponder()
                self.view.endEditing(true)
            default:
                break
            }
        }
        if text?.count == 0 {
            switch textField {
            case self.paymentView.firstDigit:
                self.paymentView.firstDigit.becomeFirstResponder()
                self.paymentView.firstDigit.backgroundColor = .red
            case self.paymentView.secondDigit:
                self.paymentView.firstDigit.becomeFirstResponder()
                self.paymentView.firstDigit.backgroundColor = .red
            case self.paymentView.thirdDigit:
                self.paymentView.secondDigit.becomeFirstResponder()
                self.paymentView.secondDigit.backgroundColor = .red
            case self.paymentView.fourthDigit:
                self.paymentView.thirdDigit.becomeFirstResponder()
                self.paymentView.thirdDigit.backgroundColor = .red
            default:
                break
            }
        }
    }

The above is how I tried to make textfield move to previous textfield when clear button of built-in keyboard iOS is clicked but it did not move. And the code above I copied from the source How to move cursor from one text field to another automatically in swift ios programmatically?

Visal Sambo
  • 1,270
  • 1
  • 19
  • 33

2 Answers2

0

My approach was like this:

import UIKit

class ViewController1: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var text1: UITextField!

    @IBOutlet weak var text2: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        text1.delegate = self
        text2.delegate = self
    }

    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        if textField == text1 {
            textField.text = ""
            textField.resignFirstResponder()
            text2.becomeFirstResponder()
        }
        return false
    }

}
0

I have worked with this just follow these steps and you will get results as per your need:

 @IBOutlet weak var txt4: UITextField!
 @IBOutlet weak var txt3: UITextField!
 @IBOutlet weak var txt2: UITextField!
 @IBOutlet weak var txt1: UITextField!

Add textField Delegate in view controller

In viewDidLoad assign delegate:

  txt1.delegate = self
  txt2.delegate = self
  txt3.delegate = self
  txt4.delegate = self

Then add this code you will get as you want

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            if (textField == txt1) {
               txt2.becomeFirstResponder()
            }else if (textField == txt2) {
               txt3.becomeFirstResponder()
            }else if (textField == txt3) {
               txt4.becomeFirstResponder()
            }else if (textField == txt4) {
             //here

            var str = self.txt1.text! + self.txt2.text! + self.txt3.text! + self.txt4.text!
            str = str.replacingOccurrences(of: " ", with: "")
            self.verify(otp: str)
                     //  self.navigationController?.pushViewController(vc, animated: true)
            }
            return true
        }
    func textFieldDidBeginEditing(_ textField: UITextField) {
        if(textField.text?.count == 0)
        {
            textField.text = " "
        }
    }

    @objc func setNextResponder(textfield : UITextField)
    {
        textfield.becomeFirstResponder()

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

        let _char  = string.cString(using: .utf8)
       // const char * _char = [string cStringUsingEncoding:NSUTF8StringEncoding];
       // int isBackSpace = strcmp(_char, "\b");
        let isBackSpace = strcmp(_char, "\\b")

        if (isBackSpace == -92) {
            // NSLog(@"Backspace was pressed");



            if (textField == txt4)
            {
                if(textField.text!.count == 2)
                {

                }
                else{
                    self.perform(#selector(setNextResponder), with: txt3, afterDelay: 0.01)
                   txt3.text = " "
                }
            }
            else if (textField == txt3)
            {
                if(textField.text!.count == 2)
                {

                }
                else{
                    self.perform(#selector(setNextResponder), with: txt2, afterDelay: 0.01)
                    txt2.text = " "

                }
            }
            else if (textField == txt2)
            {
                if(textField.text!.count == 2)
                {

                }
                else{
                    self.perform(#selector(setNextResponder), with: txt1, afterDelay: 0.01)
                    txt1.text = " "
                }
            }
            else if (textField == txt1)
            {

                if(textField.text!.count == 2)
                {

                }
                else{
                    textField.resignFirstResponder()

                }

            }
        }
        if (string.count > 1 && !(Scanner.init(string: string).scanInt(nil)))
        {
        return false;
        }

        let oldLength = textField.text!.count
        let replacementLength = string.count
        let rangeLength = range.length
       let newLength = oldLength - rangeLength + replacementLength


        // This 'tabs' to next field when entering digits
        if (newLength == 2) {
            if (textField == txt1)
            {
                self.perform(#selector(setNextResponder), with: txt2, afterDelay: 0.01)

            }
            else if (textField == txt2)
            {
                self.perform(#selector(setNextResponder), with: txt3, afterDelay: 0.01)

            }
            else if (textField == txt3)
            {
                self.perform(#selector(setNextResponder), with: txt4, afterDelay: 0.01)

            }
            else if(textField == txt4)
            {
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
//                let vc = self.storyboard?.instantiateViewController(withIdentifier: "navVC") as! NavigationViewController
//               vc.modalPresentationStyle = .fullScreen
//                    self.present(vc, animated: true, completion: nil)
                    var str = self.txt1.text! + self.txt2.text! + self.txt3.text! + self.txt4.text!
                    str = str.replacingOccurrences(of: " ", with: "")
                    self.verify(otp: str)
                }
            }



        }

        return newLength <= 2;
    }