- TOUCHkit in a Nutshell
- Intercepting and Forwarding Touch Events
- Implementing the TOUCHkit Overlay View
- Using TOUCHkit With Your Application / Trying out TOUCHkit
Intercepting and Forwarding Touch Events
The key to TOUCHkit lies in intercepting touch events, creating a floating presentation above your normal interface, and then forwarding those events on to your application.
A TOUCHkit view lies on top of your interface. The custom window class grabs user touch events and presents them as circles in the TOUCHkit view. It's then responsible for forwarding them as if the user were interacting with a normal UIWindow. To accomplish this, TOUCHkit uses "event forwarding."
Event forwarding is achieved by calling a secondary event handler. The TOUCHOverlayWindow class overrides UIWindow's sendEvent: method to force touch drawing and then invokes its superclass implementation to return control to the normal responder chain.
The following implementation is drawn from Apple's Event Handling Guide for iOS. It collects all the touches associated with the current event, allowing multitouch as well as single touch interactions, dispatches them to TOUCHkit view layer, and then redirects them to the window via the normal UIWindow sendEvent: implementation.
Listing 1
@implementation TOUCHOverlayWindow - (void) sendEvent:(UIEvent *)event { // Collect touches NSSet *touches = [event allTouches]; NSMutableSet *began = nil; NSMutableSet *moved = nil; NSMutableSet *ended = nil; NSMutableSet *cancelled = nil; // Sort the touches by phase for event dispatch for(UITouch *touch in touches) { switch ([touch phase]) { case UITouchPhaseBegan: if (!began) began = [NSMutableSet set]; [began addObject:touch]; break; case UITouchPhaseMoved: if (!moved) moved = [NSMutableSet set]; [moved addObject:touch]; break; case UITouchPhaseEnded: if (!ended) ended = [NSMutableSet set]; [ended addObject:touch]; break; case UITouchPhaseCancelled: if (!cancelled) cancelled = [NSMutableSet set]; [cancelled addObject:touch]; break; default: break; } } // Create pseudo-event dispatch if (began) [[TOUCHkitView sharedInstance] touchesBegan:began withEvent:event]; if (moved) [[TOUCHkitView sharedInstance] touchesMoved:moved withEvent:event]; if (ended) [[TOUCHkitView sharedInstance] touchesEnded:ended withEvent:event]; if (cancelled) [[TOUCHkitView sharedInstance] touchesCancelled:cancelled withEvent:event]; // Call normal handler for default responder chain [super sendEvent: event]; } @end