Touches take a long and circuitous route to their destination. Officially, they go up the responder chain, which starts at the first responder, and then goes from the deepest-touch-including view to its view controller, to the next-up touch-including view, etc.
But the real picture is even more complicated, since, in finding the deepest-touch-including view to go to, the touch essentially "asks" the highest-level view for that info by calling the hitTest:withEvent:
method. This allows some superviews to hijack touches, which can be very useful, as in UIScrollView
, which sometimes does things (scrolls/zooms) before its subviews know what's going on.
Here are a few tips to help determine why a view might not be responding to touches:
- Override
[hitTest:withEvent:
]1 on each of your views and NSLog
when they get hit to see who is being considered for the responder chain.
- Use the undocumented (and-therefore-take-it-out-before-you-submit)
UIView
method recursiveDescription
to check the frames of all your views at runtime. Views display beyond their frame sizes by default, so they may appear ok, but have smaller sizes logically than visually -- and the touches respond based on the logical (not visual) sizes.
- This may sound dumb, but double-check that your methods are correctly connected to the output you're looking for. For example, if you're expecting your - [MyClass buttonPressed] method to get called when a
UIButton
is touched, double-check that you've added your MyClass
instance and @selector(buttonPressed)
as a target/action pair for that button.
- If none of those work, override
touchesBegan:withEvent:
with NSLog
messages to see where the touches are going up the responder chain.
And, you already know this, but watch out for the userInteractionEnabled
flag!
Hopefully that's enough to isolate the problem.