Detect if certain UIView was touched amongst other UIViews

I have 3 UIViews, layered on top of one large uiview. I want to know if the user touches the top one and not care about the other ones. I will have a couple of buttons in the second UIView and a UITable in the 3rd UIView.

Problem is I turn userInteractionEngabled on on the first view and that works, but all the other views respond in the same way even if I turn it off. If I disable userInteractionEnabled on self.view none of them respond. I also can't detect which view was touched in the touchesBegan delegate method.

My code:

UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 150)];
aView = userInteractionEnabled = YES;
[self.view addSubview:aView];

UIView *bView = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 320, 50)];
bView.userInteractionEnabled = NO;
[self.view addSubview:bView];

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//This gets called for a touch anywhere
}

Solution 1:

In order to check whether certain view inside another view was touched you can use hitTest.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

In your custom implementation of touchesBegan check every touch in touches set. The point for hitTest method can be obtained using

- (CGPoint)locationInView:(UIView *)view;

method, where the view is your superView (the one that contains other views).

EDIT: Here's a fast custom implementation:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    CGPoint locationPoint = [[touches anyObject] locationInView:self];
    UIView* viewYouWishToObtain = [self hitTest:locationPoint withEvent:event];
}

I hope this was helpful, Paul

Solution 2:

In my case the UIView I wanted to find was not returned by the hitTest. But the following code worked better:

    CGPoint locationPoint = [[touches anyObject] locationInView:self.view];
    CGPoint viewPoint = [myImage convertPoint:locationPoint fromView:self.view];
    if ([myImage pointInside:viewPoint withEvent:event]) {
       // do something
    }