Detect touch globally

2019-02-15 10:46发布

问题:

I trying to figure out how to solve this (fairly) simple problem but I failing miserably, so I really need your advice.

My application consists of a uitabbar with several tabs. In one of them I have a bunch of UIImageViews each of which represents the thumbnail of a picture. Similarly as you remove apps from the iPhone by pressing for a second on the app icon, I implemented a UILongPressGestureRecognizer recognizer which starts wobbling the thumb. If the user taps on the 'X' that appears on the corner of the thumb the picture gets removed.

The logic that starts and stops the wobbling animation is inside a subclass of UIImageView that is used to show the thumb.

What I'm trying to do is cancel the wobble effect if the user presses anywhere else outside the thumb. Ideally, if possible, I would prefer to place the code that detects this cancel touch inside the UIImageView subclass.

回答1:

To catch all touch events globally I ended up subclassing UIWindow as follows:

//  CustomUIWindow.h
#import <UIKit/UIKit.h>

#define kTouchPhaseBeganCustomNotification @"TouchPhaseBeganCustomNotification"

@interface CustomUIWindow : UIWindow
@property (nonatomic, assign) BOOL enableTouchNotifications;
@end

//  CustomUIWindow.m
#import "CustomUIWindow.h"

@implementation CustomUIWindow

@synthesize enableTouchNotifications = enableTouchNotifications_;

- (void)sendEvent:(UIEvent *)event
{
    [super sendEvent:event];  // Apple says you must always call this!

    if (self.enableTouchNotification) {
        [[NSNotificationCenter defaultCenter] postNotificationName:kTouchPhaseBeganCustomNotification object:event];
    }
}@end

Then whenever I need to start listening to all touches globally I do the following:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(stopThumbnailWobble:)
                                             name:kTouchPhaseBeganCustomNotification
                                           object:nil];

((CustomUIWindow *)self.window).enableTouchNotification = YES;   

In stopThumbnailWobble I remove the observer and process the UITouch event to decide whether to remove the thumb or not:

- (void)stopThumbnailWobble:(NSNotification *)event
{    
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                    name:kTouchPhaseBeganCustomNotification 
                                                  object:nil];
    ((CustomUIWindow *)self.window).enableTouchNotification = NO;

    UIEvent *touchEvent = event.object;
    // process touchEvent and decide what to do
    ...

Hope this helps others.



回答2:

If you must include the code detection in your uiimageview subclass then I would tell the appdelegate that a touch was received and where. The app delegate could then either tell all your uiimageviews or tell the viewcontroller which would tell it's uiimageviews.

untested code:

appDelegate = (myAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate touchedAt:(int)xPos yPos:(int)yPos];