Search code examples
iosswiftuikit

Only allow UILongPressGestureRecognizer on parent view


Problem

I need to ensure that UILongPressGestureRecognizer is only applied to the parent view and doesn't get called when I long press on a child view - I should also note that setting the child view variable isUserInteractionEnabled to false is not an option in my case as the child view requires a tap gesture for other purposes.

My code so far (pretty basic):

(Notice when you run it how the long press gesture is also triggered when long pressing over the subview - I want the long press to only be triggered if the user is pressing on the main/ parent view)

class ExampleViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    
    let smallView: UIView = {
        let view = UIView(frame: CGRect(x: 30, y: 30, width: 100, height: 100))
        view.backgroundColor = .red
        return view
    }()
    view.addSubview(smallView)
    
    let longPressMultiSelection = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
    longPressMultiSelection.minimumPressDuration = 0.5
    view.addGestureRecognizer(longPressMultiSelection)
}

@objc func handleLongPress(_ sender: UILongPressGestureRecognizer? = nil) {
    if sender?.view == self.view {
        switch sender?.state {
        case .began, .changed:
            print("here")
        case .ended, .cancelled, .failed:
            print("ended")
        default:
            print("error")
        }
    }
}
}

Any help is very much appreciated 😅


Solution

  • You are the gesture recognizer delegate, so use your mighty delegate powers to decide whether the gesture recognizer should operate:

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        !smallView.bounds.contains(gestureRecognizer.location(in: smallView))
    }