4th April 2012

Monitoring all iOS touches

Guides | Tutorial By 5 years ago

There are probably a dozen ways to capture and monitor touches on the iOS. Some require a lot of work, including method swizzling, or using private/undocumented APIs which might result in your application being rejected from the AppStore.

When I was given the task of monitoring all touches in an application, I wanted to do it using 100% public APIs. As the goal of this project was to be compiled into a Framework, subclassing UIApplication was a bit useless, and method swizzling wasn’t something I wanted to do. I turned to UIGestureRecognizers.

You can subclass a UITapGestureRecognizer and intercept (without cancelling) all touches on a view the recognizer is attached to. There’s actually very little coding for this.

First make a subclass of UITapGestureRecognizer. Import the <UIKit/UIGestureRecognizerSubclass.h> header, which gives us extra methods to override in our subclass. You will notice this header defines the touchesBegan:, touchesMoved: etc etc methods you might recognise from the UIResponder class. Override all of those methods, for now I will just log when the event is called so we can see it working.

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
	NSLog(@"touchesBegan: %@", touches.allObjects);

	[super touchesBegan:touches withEvent:event];

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
	NSLog(@"touchesMoved: %@", touches.allObjects);

	[super touchesMoved:touches withEvent:event];

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
	NSLog(@"touchesEnded: %@", touches.allObjects);

	[super touchesCancelled:touches withEvent:event];

- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
	NSLog(@"touchesCancelled: %@", touches.allObjects);

	[super touchesCancelled:touches withEvent:event];

In your app delegate’s application:didFinishLaunchingWithOptions: method, after your UIWindow is initialised add the gesture recognizer. Don’t forgot to make it not cancel touches otherwise they will never be seen by your window.

AllTouchesGestureRecognizer* recognizer = [[AllTouchesGestureRecognizer alloc] initWithTarget:nil action:nil];
[recognizer setCancelsTouchesInView:NO];
[self.window addGestureRecognizer:recognizer];
[recognizer release];

Run and play with the application, you will see touches being logged. You may notice that if you move your finger around only the first few touches are logged, but none after this point. For this you will need to override the ignoreTouch:forEvent: method, but don’t pass it up to super.

- (void) ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event
	//	Overriding this prevents touchesMoved:withEvent:
	//	not being called after moving a certain threshold

Run the application again and presto, all touches are being logged. The endpoint for this project can be downloaded here.

When a keyboard is shown in your application, it sits on a new window, you can look at the UIWindowDidBecomeVisibleNotification message to add one of these recognizers to any new windows that appear.

Recommended Posts

iOS performSelector with multiple parameters

Post by 5 years ago

On iOS the built in convenience method performSelector method call only allows for up to 2 parameters. - (void) aMethod { [self performSelector:@selector(doSomethingWithObject:otherObject:) withObject:@(1) withObject:@(2)]; } - (void) doSomethingWithObject:(id) object otherObject:(id) otherObject { // Code

Got an idea?

We help entrepreneurs, organizations and established brands from around
the country bring ideas to life. We would love to hear from you!