Mathias
Mathias

Reputation: 566

How to run code when user stops pressing a button?

I have an eye button next to my password textfield which is suppose to set to false the secure text entry property of the textfield for the time the user presses, it should end when the user removes his finger.

I successfully managed to set the property to false when the user presses using a target with the touchUpInside event, but I don't know how to detect that this event has stopped. And this what I'm looking for.

Before that I have used the long press gesture recognizer, but the problem is that the code was taking too much time to kick in. Which is normal because it's a long presse but it is not the behavior I want.

My code was :

let gesture = UILongPressGestureRecognizer(target: self, action: #selector(eyePressed(sender:)))
passwordEyeButton.addGestureRecognizer(gesture)

@objc func eyePressed(sender : UILongPressGestureRecognizer){
    switch sender.state {
    case .began :
        passwordEyeButton.setImage(eyeImage, for: .normal)
        passwordTextField.isSecureTextEntry = false
    case .ended :
        passwordEyeButton.setImage(crossedEyeImage, for: .normal)
        passwordTextField.isSecureTextEntry = true
    default :
        print("default state")
    }
}

Upvotes: 1

Views: 368

Answers (3)

Gustavo Vollbrecht
Gustavo Vollbrecht

Reputation: 3256

You need to manage 3 events: .touchDown, .touchUpInside and .touchUpOutside.

Your intention is to show the password when the button is pressed, and hide it when the finger is released, and therefore if you only implement .touchUpInside to detect that user stopped pressing a button it will NOT work if it releases the finger outside the button.

override func viewDidLoad() {
    super.viewDidLoad()
    button.addTarget(self, action: #selector(showPassword), for: .touchDown)
    button.addTarget(self, action: #selector(hidePassword), for: .touchUpInside)
    button.addTarget(self, action: #selector(hidePassword), for: .touchUpOutside)   
}

@objc func showPassword(_ sender: Any) {
    print("show password")
}

@objc func hidePassword(_ sender: Any) {
    print("hide password")
}

Upvotes: 2

Robert Dresler
Robert Dresler

Reputation: 11160

I would add two targets to UIButton for two events:

  • touchDown for handle when button is pressed
  • touchUpInside for handle when user move his finger from the button

override func viewDidLoad() {
    super.viewDidLoad()
    passwordEyeButton.addTarget(self, action: #selector(pressBegan(_:)), for: .touchDown)
    passwordEyeButton.addTarget(self, action: #selector(pressEnded(_:)), for: .touchUpInside)
}

@objc func pressBegan(_ sender: UIButton) {
    passwordEyeButton.setImage(eyeImage, for: .normal)
    passwordTextField.isSecureTextEntry = false
}

@objc func pressEnded(_ sender: UIButton) {
    passwordEyeButton.setImage(crossedEyeImage, for: .normal)
    passwordTextField.isSecureTextEntry = true
}

Upvotes: 1

Sam Bing
Sam Bing

Reputation: 2872

Add a touch down event and a touch up inside event for your button:

You can use the storyboard to add them so no need to add the targets manually.

//Touch down
@IBAction func touched(_ sender: UIButton) {
        print("show password")
}

//Touch up inside 
 @IBAction func touchUp(_ sender: UIButton) {
        print("hide password")
 }

Upvotes: 1

Related Questions