1

I have a UIButton that is only reacting to my tap gestures when I tap on a very small sub-area within it. I'm assuming that maybe another view is swallowing my gestures when I tap in other places within the button.

the question is.. is there a way to know which UIView exactly is receiving the taps? I know I can brute force it an attach all gesture handlers to all of my views.. but seems like too much work. any ideas?

update: Ahmed's answer below worked perfectly.. I also added to it UIView's recursiveDescription to find the offending view quickly.

ie if i put a breakpoint on the NSLog line:

- (void)sendEvent:(UIEvent *)event
{
    [super sendEvent:event];
    UIView *touchReceipientView =((UITouch *)[event.allTouches anyObject]).view;
    NSLog(@"View = %@ ",touchReceipientView);
}

I get this output (as an example):

(lldb) po [touchReceipientView recursiveDescription]
<UIView: 0x1fd16470; frame = (0 430; 320 40); layer = <CALayer: 0x1fd164d0>>
   | <UIButton: 0x1fd13030; frame = (297 0; 18 19); opaque = NO; tag = 11; layer = <CALayer: 0x1fd130f0>>
   |    | <UIImageView: 0x1fd13190; frame = (-41 -40.5; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x1fd131f0>>
   |    | <UIImageView: 0x1fd14d00; frame = (1 2; 16 15); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1fdc8e50>>

which made me identify the offending UIView immediately!

Community
  • 1
  • 1
abbood
  • 23,101
  • 16
  • 132
  • 246
  • Loop through the views, starting from the key window of your app, and send `isFirstResponder` to them. –  Jul 17 '13 at 08:44
  • gestureRecognizer.view – Desdenova Jul 17 '13 at 08:46
  • @Desdenova If I already had the gestureRecognizer object I think this question would be trivial wouldn't it? – abbood Jul 17 '13 at 08:47
  • @H2CO3.. interesting.. i'm not sure what to expect out of that.. but i'll try it anyways and see what happens.. thanks! – abbood Jul 17 '13 at 08:48
  • my bad, thought you were using recognizer. – Desdenova Jul 17 '13 at 08:50
  • In your loop you can also print the frames / add a coloured border so you can see where everything is. – Wain Jul 17 '13 at 09:01
  • i'd look at touch.view – Exothug Jul 17 '13 at 09:03
  • @H2CO3 The view receiving the touches will probably not be the first responder. `"UIKit automatically sets the text field or text view that a user taps to be the first responder; Apps must explicitly set all other first responder objects with the becomeFirstResponder method."` (http://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html#//apple_ref/doc/uid/TP40009541-CH4-SW2). – Ahmed Mohammed Jul 17 '13 at 09:13
  • @AhmedMohammed Well, the first responder is called the first responder because it's the one that receives events before any other object in the responder chain. –  Jul 17 '13 at 09:14
  • @H2CO3 That is for the keyboard events. Touch events are received by the view they are on. But UIKit does not automatically make it first responder. If it did, textfields would resign first responder when you tap somewhere else and the keyboard would disappear. But that does not happen. – Ahmed Mohammed Jul 17 '13 at 09:27
  • It doesn't answer your question, but to debug overlapping views you can set "Blend Color Layers" in the Simulator. Overlapping areas of views are shown in a darker colour. – nevan king Jul 17 '13 at 10:13

1 Answers1

2

You can subclass the UIApplication and see who is receiving the events.

and in main.m,

@interface MyApplication : UIApplication

@end


@implementation MyApplication

- (void)sendEvent:(UIEvent *)event
{
    [super sendEvent:event];
    NSLog(@"View = %@",  ((UITouch *)[event.allTouches anyObject]).view);
}

@end





int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, NSStringFromClass([MyApplication class]), NSStringFromClass([MyAppDelegate class]));
    }
}
Ahmed Mohammed
  • 1,134
  • 8
  • 10