1

I have a button with a long-press gesture recognizer assigned to it.

I would like the button to remain highlighted (just as it would during a normal click) for the duration of a long press, AND for the single click NOT to be triggered after the long press.

What I have tried so far:

To illustrate why it might be important to have this functionality, let's take the example of a UILabel that displays a number, and a button that increments that number.

A single click should increment the number by 1, and a long-press should increment it by 10 (a timer could be added later that "auto-increments" the number as the finger is held down, but for the purposes of this example, I am leaving that out).

So I started with this code:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var numberDisplayLabel: UILabel!
    @IBOutlet weak var incrementNumberButton: UIButton!
    @IBOutlet var buttonLPGR: UILongPressGestureRecognizer!

    var numVal = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        numberDisplayLabel.text = String(numVal)
    }

    @IBAction func buttonClicked(_ sender: UIButton) {
        print("button clicked")
        numVal += 1
        numberDisplayLabel.text = String(numVal)
    }

    @IBAction func longPressOnButtonRecognized(_ sender: UILongPressGestureRecognizer) {
        print("long press recognized, state: \(sender.state.rawValue)")
        if (sender.state == .ended) {
            numVal += 10
            numberDisplayLabel.text = String(numVal)
        }
    }

}

Let's try to single click and see if that works:

enter image description here

Yes it does, YAY.

Now let's see what happens if we long-press it:

enter image description here

So... you can see that the button highlights when touched down (as normal), but when the long press is recognized (enters the .began state), the highlight is cancelled. When we finally release the touch, the number is incremented by 10 as expected.

But what if we want the button to remain highlighted during the entire process...

we could try adding this code to viewDidLoad():

buttonLPGR.cancelsTouchesInView = false

This should prevent the initial touch from being cancelled by the long-press recognition.

Let's see! :

enter image description here

Hmmm well we got what we wanted as far as the highlighting, but now, since the regular press is no longer cancelled by the long press, the button's touchUpInside action function is still called and so the number is incremented not only by 10, but by 1 also.

This is where I don't know what to do from this point.

So, once again: How can we have the button remain highlighted (just as it would during a normal click) for the duration of a long press, AND for the single click NOT to be triggered after the long press?

If the touch framework provides a way of doing this without a work-around, that would be preferred.

Nerdy Bunz
  • 6,040
  • 10
  • 41
  • 100
  • in the .began state update your button highlight image to be for: .normal and on .ended reset the original button images for each state. – Alex Bailey Jan 05 '19 at 01:51
  • `UIButton` control events seem to me perfectly adequate to handle this without any gesture recognizers. The button tells you about down and up and handles its highlighting, an NSTimer (and a start time) tells you about time elapsed. Isn't that sufficient for all the behavior described here? – danh Jan 05 '19 at 02:04
  • thanks @danh... so making a custom button that does its own long-click handling?... the only way to trigger a function in the Viewcontroller from the code in the custom button would be with a delegate, correct? – Nerdy Bunz Jan 05 '19 at 08:58
  • @BooberBunz, UIControl implements this https://developer.apple.com/documentation/uikit/uicontrol/1618259-addtarget – danh Jan 05 '19 at 16:09
  • but there is no UIControl.longpress so how can you use the addTarget method to communicate long presses? – Nerdy Bunz Jan 06 '19 at 00:17

0 Answers0