Home > Software design >  How to catch all events in Swift without breaking other event handlers
How to catch all events in Swift without breaking other event handlers

Time:12-03

How can I catch any touch up event in my application view without affecting any other event in subview or subview of the subview?

Currently whenever I add UILongPressGestureRecognizer to my root view, all other addTarget functions break in subviews and their subviews.


func gestureRecognizer(_: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith: UIGestureRecognizer) -> Bool {
   return true
}

override func viewDidLoad() {
   let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
   button.setTitle("Click me", for: .normal)
   button.addTarget(self, action: #selector(buttonClick), for: .touchDown)
   self.view.addSubview(button)
        
   initLongTapGesture() // This kills the button click handler.
}

func initLongTapGesture () {
   let globalTap = UILongPressGestureRecognizer(target: self, action: #selector(tapHandler))
   globalTap.delegate = self
   globalTap.minimumPressDuration = 0
   self.view.addGestureRecognizer(globalTap)
}

@objc func tapHandler(gesture: UITapGestureRecognizer) {
   if ([.ended, .cancelled, .failed].contains(gesture.state)) {
      print("Detect global touch end / up")
   }
}

@objc func buttonClick() {
   print("CLICK") // Does not work when initLongTapGesture() is enabled
}


CodePudding user response:

The immediate solution to allow the long press gesture to work without preventing buttons from working is to add the following line:

globalTap.cancelsTouchesInView = false

in the initLongTapGesture function. With that in place you don't need the gesture delegate method (which didn't solve the issue anyway).


The big question is why are you setting a "long" press gesture to have a minimum press duration of 0?

If your goal is to monitor all events in the app then you should override the UIApplication method sendEvent. See the following for details on how to subclass UIApplication and override sendEvent:

Issues in overwriting the send event of UIApplication in Swift programming

You can also go through these search results:

https://stackoverflow.com/search?q=[ios][swift] override UIApplication sendEvent


Another option for monitoring all touches in a given view controller or view is to override the various touches... methods from UIResponder such as touchesBegan, touchesEnded, etc. You can override these in a view controller class, for example, to track various touch events happening within that view controller.


Unrelated but it is standard to use the .touchUpInside event instead of the touchDown event when handing button events.

  • Related