Search code examples
swiftuibuttonuitextfielduitextfielddelegate

UITextField rightView image and button?


I'm having 2 problems with UITextView. I have a UIViewController that has 5 UITextField. UITextField1 and UITextField2 are always visible and cannot be hidden by the user. If the user taps on a button, it adds (isHidden property is set to false) up to 3 more UITextFields.

Each of those UITextFields should show as a .rightView a custom UILabel that shows the left characters. In addition to that, the 3 additional UITextFields should also add as a .rightView a UIButton that when it's tapped it should animate textField.isHidden = true so that it makes the illusion that it deletes the UITextField.

The problem

The delete UIButton of the right view, doesn't work (ie doesnt hide the corresponding UITextField and I'm not sure why. Right now when you tap the delete UIButton it sort of hides the button itself which is odd

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

    guard let text = textField.text else { return true }
    let newLength = text.count + string.count - range.length

    let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 55, height: 25))
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
    label.font = UIFont(name: Fonts.OpenSans_Light, size: 14)

    if textField === thirdChoiceTextField || textField === forthChoiceTextField || textField === fifthChoiceTextField {
        let button = UIButton(frame: CGRect(x: rightView.frame.width - 30, y: 0, width: 25, height: 25))
        button.setBackgroundImage(UIImage(named: "icon_cancel_dark"), for: .normal)
        button.addTarget(self, action: #selector(self.hideTextField(textField:)), for: .touchUpInside)
        rightView.addSubview(button)
    }

    rightView.addSubview(label)
    textField.rightView = rightView
    textField.rightViewMode = .whileEditing
    label.textAlignment = .center

    if newLength <= 35 {
        label.text =  String(50 - newLength)
        label.textColor = .lightGray
    }
    else {
        label.text =  String(50 - newLength)
        label.textColor = UIColor.red
    }

    return newLength < 50
}


@objc func hideTextField(textField: UITextField) {
    if !textField.isHidden {
        UIView.animate(withDuration: 0.2) {
            textField.isHidden = true
        }
    }
}

Solution

  • In func hideTextField(textField: UITextField) method, the parameter should not be a UITextField, it should be a UIButton itself as below,

    @objc func hideTextField(_ sender: UIButton) {
        ...
    }
    

    and the below line

    button.addTarget(self, action: #selector(self.hideTextField(textField:)), for: .touchUpInside)
    

    Will change to

    button.addTarget(self, action: #selector(self.hideTextField(_:)), for: .touchUpInside)
    

    And now you can apply the animation as below,

    @objc func hideTextField(_ sender: UIButton) {
        if let  field = sender.superview?.superview as? UITextField, !field.isHidden {
            UIView.animate(withDuration: 0.2) {
                field.isHidden = true
            }
        }
     }