UISystemGateGestureRecognizer and delayed taps nea

2019-01-23 14:02发布

问题:

What are the standard UISystemGestureGateGestureRecognizers installed on the top level UIView of an iOS app for?

My app consists of two views - one fills the top half of the screen, the other is a custom keyboard and fills the bottom half. I found that taps on the space bar didn't always work and after some investigation found that the timing of tap events in the bottom 20 pixels or so was different to the rest of the view. For most of the view the period between touchesBegan/Ended was about 100ms, where as for the space bar it was 1-2ms. (My app is an emulator and this is too fast for it to detect the key press).

After some more digging I found the main UIView of the application (ie: my main view's superview) has 2 UISystemGestureGateGestureRecognizer's installed. By removing them in ViewDidAppear the bottom of the screen is no longer affected. (Presumably these are cancelling the touch press events to my keyboard hence the faster timing).

These system recognizers are present on at least iOS 5 through 7 and on both iPad and iPhone. I thought they may be related to swipe from top/bottom but this functionality still works with them removed.

So I have a fix, but I'd like to understand more about what's going on here - in particular what I might be breaking by removing these.

回答1:

This delayed touches bothered me too. Just as an addition to what's said before, here's a simple fix:

override func viewDidAppear(_ animated: Bool) {
    let window = view.window!
    let gr0 = window.gestureRecognizers![0] as UIGestureRecognizer
    let gr1 = window.gestureRecognizers![1] as UIGestureRecognizer
    gr0.delaysTouchesBegan = false
    gr1.delaysTouchesBegan = false
}

no need to remove those gesture recognizers. just add this to the main view controller.



回答2:

It appears that these recognizers are meant to prevent accidental touches near the top and bottom of the screen. They aren't configured with any targets, but can (like any UIResponder) absorb touches to prevent them from being passed up the responder chain.

Notes (tested on iOS 7.1):

  • Both gesture recognizers are always present in the key window.
  • I inspected both gestures' _targets ivar, and found they aren't configured with any targets at all. Swizzled out addTarget:action: to verify that targets weren't being added or removed on the fly.
  • delegate is always nil for both instances.
  • If you disable the gesture recognizers, they will re-enable themselves
  • The gesture that that doesn't delay content touches fires when you drag up from the bottom or drag down from the top. I couldn't trigger the instance that delays touches.