Search code examples
iosswiftkeyboarduitextfielddelegate

Auto hidden keyboard after enter six characters


I am a swift beginner. I implemented this functionality in ViewController, but I don't want to write such code in every ViewController. I want to implement it through a protocol, but something is wrong.

import UIKit

@objc protocol TextFieldAutoHiddenKeyboard: class {
    var textFieldAutoHidenLenth: UInt {get set} 
}

extension TextFieldAutoHiddenKeyboard where Self: UIViewController {

    func autoHiddenKeyboardWhenFillUpTextFiled(textField textF: UITextField, autoHidenLenth: UInt) {
        textFieldAutoHidenLenth = autoHidenLenth

        let textFieldDidChangeActionName = "textFieldDidChange(textField:)"
        let textFieldDidChangeAction = Selector(textFieldDidChangeActionName)
        textF.addTarget(self, action: textFieldDidChangeAction, for: .editingChanged)

        let dismissKeyboardActionName = "dismissKeyboard"
        let dismissKeyboardAction = Selector(dismissKeyboardActionName)
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: dismissKeyboardAction)
        view.addGestureRecognizer(tap)
      //textF.addTarget(self, action: #selector(textFieldDidChange(textField:autoHidenLenth:)), for: .editingChanged)
    }

    func textFieldDidChange(textField: UITextField) {
        if let text = textField.text {
            if text.count == textFieldAutoHidenLenth {
                textField.resignFirstResponder()
            }
        }
    }

    func dismissKeyboard() {
        view.endEditing(true)
    }

    //@objc func textFieldDidChange(textField: UITextField, autoHidenLenth: UInt) {
    //    if let text = textField.text {
    //        if text.count == autoHidenLenth {
    //           textField.resignFirstResponder()
    //        }
    //    }
    //}
}
  1. Why my app crash. EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  2. By creating an Action using a Selector, #selector(textFieldDidChange(textField:autoHidenLenth:)), I don't know how to pass the second argument to function. For example, the parameter autoHidenLenth.
  3. How to implement this function correctly through Protocol?

Demo picture
(source: recordit.co)


Solution

  • As you need to enable this feature for multiple textfields, you can use this.

    References: Link1, Link2

    private var autoHiddenLengthAssociationKey: UInt8 = 0
    
    extension UITextField {
    
        private var autoHiddenLenth: Int? {
            get {
                return objc_getAssociatedObject(self, &autoHiddenLengthAssociationKey) as? Int
            }
            set {
                objc_setAssociatedObject(self, &autoHiddenLengthAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
            }
        }
    
        func enableAutoHidingFeature(maxLength: Int) {
            autoHiddenLenth = maxLength
            self.addTarget(self, action: #selector(textDidChange(textField:)), for: .editingChanged)
        }
    
        @objc func textDidChange(textField: UITextField) {
    
            guard let maxLength = autoHiddenLenth, let text = textField.text else { return }
    
            if text.count == maxLength {
                textField.resignFirstResponder()
            }
        }
    }
    

    You can enable this by calling:

    textField.enableAutoHidingFeature(maxLength: 6)