2
votes

I have a collection view/scrollview where I'm adding my UILongPressGestureRecognizer. It works, but state .Began only gets fired together with state. Ended. That doesn't work for me as I want to also track the state .Changed to get the gesture.locationInView.

The problem I found is that it's conflicting with the Scroll gesture of the collection view .

If I set scrollEnabled to false, everything works as expected.

In my viewDidLoad I have

let longPressedGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(PhotosViewController.Scrubber(_:)))
self.scrubberCollectionView.addGestureRecognizer(longPressedGestureRecognizer)
longPressedGestureRecognizer.minimumPressDuration = 0.6
longPressedGestureRecognizer.delegate = self

self.scrubberCollectionView.addGestureRecognizer(longPressedGesture)

I also tried adding these to try to make one gesture fail when the pan gesture is enabled… (and I tried the shouldRecognizeSimultaneouslyWithGestureRecognizer as well.

longPressedGestureRecognizer.requireGestureRecognizerToFail(scrubberCollectionView.panGestureRecognizer)

 func overridePan(gestureRecognizer: UILongPressGestureRecognizer, shouldRequireFailureOfGestureRecognizer otherGestureRecognizer: UIPanGestureRecognizer ) -> Bool {
        return (gestureRecognizer == longPressedGesture && otherGestureRecognizer == self.scrubberCollectionView.panGestureRecognizer )
    }

…to no avail.

For the main function I have

        func Scrubber(gesture: UILongPressGestureRecognizer) {
            if (gesture.state == .Began ) {
                 print("Began")
            }
            else if (gesture.state == .Changed) {
                 print("Changed")
            }
            else if (gesture.state == .Ended){
                 print("Ended")
            }
        }

When I long press I get no events on touch down, then on touch up I get these results:

Began
Ended

The actual long press is working, if I tap then the Scrubber function is not called, it's just firing both Began and Ended on the Ended state.

And added these things to viewDidLoad to try to delay the touch of the scrollview and even cancel it altogether…

self.scrubberCollectionView.delaysContentTouches = true

    let longPress = UILongPressGestureRecognizer()
    func gestureRecognizer(gestureRecognizer: UILongPressGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {

        if(touch.view == scrubberCollectionView && gestureRecognizer == longPress){
            return true
        }else{
            return false
        }
    }

…and nothing.

1

1 Answers

0
votes

I figured it out. I was adding the shouldRequireFailureOfGestureRecognizer inside viewDidLoad. It needs to be outside it.

In order to place it outside and make it work, you need to create your gesture variables (in my case "longPressedGesture") as optionals also outside viewDidLoad, like:

var longPressedGesture : UILongPressGestureRecognizer?

then inside viewDidLoad you create the gestures

 longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(PhotosViewController.Scrubber(_:)))
            longPressedGesture.delegate = self
            self.scrubberCollectionView.addGestureRecognizer(longPressedGesture)