0

I have 20+ buttons and I want to define a single UILongPressGestureRecognizer for all, is it possible?

So far this doesn't work:

let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongGesture))

B_BTN_1.addGestureRecognizer(longPressGestureRecognizer)
B_BTN_2.addGestureRecognizer(longPressGestureRecognizer)

For some reason, the longPressGestureRecognizer only works for "B_BTN_2".

But by declaring a gesture recognizer for each, it works:

let longPressGestureRecognizer1 = UILongPressGestureRecognizer(target: self, action: #selector(handleLongGesture))
let longPressGestureRecognizer2 = UILongPressGestureRecognizer(target: self, action: #selector(handleLongGesture))

B_BTN_1.addGestureRecognizer(longPressGestureRecognizer1)
B_BTN_2.addGestureRecognizer(longPressGestureRecognizer2)

EDIT:

If you'll gonna use @Andre's solution, and having many buttons, use this instead to prevent the indexing bug (takes like forever):

var buttons:[UIButton] = []
    buttons.append(B_BTN_1)
    buttons.append(B_BTN_2)
    buttons.append(B_BTN_3)
    .....
iOSNewbie
  • 85
  • 1
  • 9

2 Answers2

2

as @Andriy Savran already stated a gesture recognizer can only have one view it is attached to. you could use loops to make the setup process a little simpler...

override func viewDidLoad() {
    super.viewDidLoad()

    let button1 = UIButton(type: .system)
    let button2 = UIButton(type: .system)
    let button3 = UIButton(type: .system)
    // ...

    let buttons = [button1, button2, button3]

    for button in buttons {
        let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(sender:)))
        button.addGestureRecognizer(longPressGestureRecognizer)
    }

}

func handleLongPress(sender: UILongPressGestureRecognizer) {
    guard let button = sender.view else {
        fatalError("could not get the button attached to the gesturerecognizer")
    }

    // do something
}
André Slotta
  • 13,774
  • 2
  • 22
  • 34
1

Quote from Apple doc:

Every gesture recognizer is associated with one view. By contrast, a view can have multiple gesture recognizers, because a single view might respond to many different gestures. For a gesture recognizer to recognize touches that occur in a particular view, you must attach the gesture recognizer to that view. When a user touches that view, the gesture recognizer receives a message that a touch occurred before the view object does. As a result, the gesture recognizer can respond to touches on behalf of the view.

https://developer.apple.com/library/content/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/GestureRecognizer_basics/GestureRecognizer_basics.html#//apple_ref/doc/uid/TP40009541-CH2-SW21

So, you need to initialize gesture recognizer for each view, as you did:

But by declaring a gesture recognizer for each, it works:

let longPressGestureRecognizer1 = UILongPressGestureRecognizer(target: self, action: #selector(handleLongGesture))
let longPressGestureRecognizer2 = UILongPressGestureRecognizer(target: self, action: #selector(handleLongGesture))

B_BTN_1.addGestureRecognizer(longPressGestureRecognizer1)
B_BTN_2.addGestureRecognizer(longPressGestureRecognizer2)
Andriy Savran
  • 535
  • 3
  • 19
  • I see! Thanks for pointing this out. I thought I could create an outlet for buttons then attach a single UILongPressGestureRecognizer. It's just pain in the eyes to see repetitive lines of code just for the same declaration of a gesture recognizer. – iOSNewbie Feb 12 '17 at 09:57
  • @iOSNewbie: take a look at my solution - it contains a way to get around repetitive code... :) – André Slotta Feb 12 '17 at 09:58