How to debug who is eating my touches in UIKit?

Not a direct answer to the question, but a very common cause of vanishing touches is for a control to be in a uiview which has a smaller size than that control, but is not clipping its bounds, so you won't see that the parent view is smaller (or even possibly zero-sized).

Parent UIView size=0x0, clipToBounds=false

   Child UIButton size=100x50

=> Child Button won't get any touch events.


You can debug that by using a symbolic breakpoint:

-[UIWindow sendEvent:] & po $arg3

enter image description here Logs:

<UITouchesEvent: 0x6000026fa6d0> timestamp: 179462 touches: {(
<UITouch: 0x7f84d6f10380> phase: Began tap count: 1 force: 0.000 
window: <UIWindow: 0x7f84d6d0ad10; frame = (0 0; 375 812); autoresize = W+H; 
gestureRecognizers = <NSArray: 0x600001aa8870>; layer = <UIWindowLayer: 0x6000014bd7e0>> view: <UIView: 0x7f84d6d0bff0; frame = (0 0; 375 812); 
autoresize = W+H; layer = <CALayer: 0x6000014bdc60>> location in window: {165.66665649414062, 232.33332824707031} previous location in window: 
{165.66665649414062, 232.33332824707031} location in view: {165.66665649414062, 
232.33332824707031} previous location in view: {165.66665649414062,232.33332824707031}
)}

You can subclass UIWindow and override -[UIWindow sendEvent]:, then when it is called, use -[UIWindow hitTest:withEvent:] to test which view will receive the event.

You can then call -[UIView recursiveDescription] to print some debug information help you understand why that view received the touch event.

Remember to call [super sendEvent:] when you are done.


For those who use Storyboard and want to know how can we change the main application window class:

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow? = TestWindow()
    // ....
}

Just provide the default value for AppDelegate's window var. When the app is launched the UIApplicationMain will instantiate a delegate and ask it for the window. If the window is nil it will create a new one automatically. But if we provide a default value here, it will be used all over the app.

Tags:

Ios