iosuigesturerecognizeruitouch

How to detect someone tapping outside of a UIImageView


I have a UIImageView that is added as a subview. It shows up when a button is pressed.

When someone taps outside of the UIImageView in any part of the application, I want the UIImageView to go away.

@interface SomeMasterViewController : UITableViewController <clip>

<clip>

@property (strong, nonatomic) UIImageView *someImageView;

There are some hints in stackoverflow and Apple's documentation that sound like what I need.

However, I want to check my approach here. It's my understanding that the code needs to

  1. Register a UITapGestureRecognizer to get all touch events that can happen in an application

  2. UITapGestureRecognizer should have its cancelsTouchesInView and delaysTouchesBegan and delaysTouchesEnded set to NO.

  3. Compare those touch events with the someImageView (how? Using UIView hitTest:withEvent?)

Update: I am registering a UITapGestureRecognizer with the main UIWindow.

Final Unsolved Part

I have a handleTap:(UITapGestureRecognizer *) that the UITapGestureRecognizer will call. How can I take the UITapGestureRecognizer that is given and see if the tap falls outside of the UIImageView? Recognizer's locationInView looks promising, but I do not get the results I expect. I expect to see a certain UIImageView when I click on it and not see the UIImageView when I click in another spot. I get the feeling that the locationInView method is being used wrong.

Here is my call to the locationInView method:

- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateEnded) {
        NSLog(@"handleTap NOT given UIGestureRecognizerStateEnded so nothing more to do");
        return;        
    }

    UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
    CGPoint point = [gestureRecognizer locationInView:mainWindow];
    NSLog(@"point x,y computed as the location in a given view is %f %f", point.x, point.y);

    UIView *touchedView = [mainWindow hitTest:point withEvent:nil];
    NSLog(@"touchedView = %@", touchedView); 
}

I get the following output:

<clip>point x,y computed as the location in a given view is 0.000000 0.000000

<clip>touchedView = <UIWindow: 0x8c4e530; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <UIWindowLayer: 0x8c4c940>>

Solution

  • I think you can just say [event touchesForView:<image view>]. If that returns an empty array, dismiss the image view. Do this in the table view controller's touchesBegan:withEvent:, and be sure to call [super touchesBegan:touches withEvent:event] or your table view will completely stop working. You probably don't even need to implement touchesEnded:/Cancelled:..., or touchesMoved:....

    UITapGestureRecognizer definitely seems like overkill in this case.