views:

643

answers:

1

I am developing a simple game on iPhone and I started with a View based application, and through the UIViewController I am loading a custom UIView that contains some more UIViews and some UIImageViews. I want to detect touch events on some of the UIImageViews, but I wasn't able so far.

I've created a second project for testing purposes and figured that UIImageViews handle touch events when the hierarchy is like : UIViewController -> UIView -> UIImageView, but when it's like : UIViewController -> UIView -> UIView -> UIImageView they are not detected.

Notes:
- userInteractionEnabled is YES in all cases
- all UIViews and UIImageViews I mention above are custom subclasses.

Can you think of any reason why, when a custom UIImageView gets deeper in the view hierarchy can't receive touch events?

+1  A: 

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.

Tyler
First of all thank you for the quick response! I just had the time to examine your tips. The problem was that I didn't initialize the UIImageView with `initWithFrame`. It was your second tip that made me suspect that this was the problem : "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."
jester