Gestures are a great new feature in iOS5 they really make complex gesture recognition code a thing of the past and support rich interaction with your interfaces. In this post I am going to explain how to implement three gestures, Pan, Tap, and Rotate. If you want to see my Gesture Demo being constructed check out my demo video on YouTube.

First you have to create a new project and drag on an additional ViewController that you would like the users to interact with. Things to remember when doing this are,

1) Set the UIViewController’s Size property in the Attribute Inspector to Freeform, this will allow you to change the size of the UIView.
2)Uncheck resize from nib in your UIViewController, again shown in the Attribute Inspector. This will prevent your view from being resized to full screen.

3) In this demo I changed the view size to 200×200 so that it could be moved around the screen.
4) Your UIViewController’s class must implement UIGestureRecogniserDelegate so that you receive the notifications of when a particular gesture is fired.

Now you must drag on your gestures and drop them on this new view. This will hook up the gestureRecognisers to the view. Then you must set your UIViewController that implements UIGestureRecogniserDelegate as the delegate to each of your gestures. See the image below,

Note: Sometimes in the new Xcode if I have forgotten to do this and run the application, when I do change them to act correctly the new changes are not propagated over. I have found clean building or sometimes even restarting Xcode is required so try these first before wasting too much time debugging like I have.

Finally you have to complete the implementation of the UIGestureRecogniserDelegate the two methods required for this demo are

 -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{

The first notifies you that a gesture has begun and the second enables multiple gestures to be performed at the one time. This is important for providing fluid scale and rotate gestures.

 
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]){
        [gestureRecognizer addTarget:self action:@selector(panGestureAction:)];
    } else if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] ) {
		[gestureRecognizer addTarget:self action:@selector(pinchGestureAction:)];
	} else if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]]) {
		[gestureRecognizer addTarget:self action:@selector(rotateGestureAction:)];
	}
    else if([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]){
        [gestureRecognizer addTarget:self action:@selector(tappedGestureAction:)];
    }
	return YES;
}
 
// called when the recognition of one of gestureRecognizer or otherGestureRecognizer would be blocked by the other
// return YES to allow both to recognize simultaneously. the default implementation returns NO (by default no two gestures can be recognized simultaneously)
//
// note: returning YES is guaranteed to allow simultaneous recognition. returning NO is not guaranteed to prevent simultaneous recognition, as the other gesture's delegate may return YES
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

Finally you have to implement your Actions, here are a few that should help you get started quickly with your won rotation, pinching and panning.

 
- (void)rotateGestureAction:(UIRotationGestureRecognizer *)rotate {
    if (rotate.state == UIGestureRecognizerStateBegan) {
        prevRotation = 0.0;
    } 
 
    float thisRotate = rotate.rotation - prevRotation;
    prevRotation = rotate.rotation;
    self.view.transform = CGAffineTransformRotate(self.view.transform, thisRotate);
}
 
- (void)pinchGestureAction:(UIPinchGestureRecognizer *)pinch {		
	if (pinch.state == UIGestureRecognizerStateBegan)
		prevPinchScale = 1.0;
 
    float thisScale = 1 + (pinch.scale-prevPinchScale);
    prevPinchScale = pinch.scale;
    self.view.transform = CGAffineTransformScale(self.view.transform, thisScale, thisScale);
}
 
-(void)panGestureAction:(UIPanGestureRecognizer *)pan {
 
    if (pan.state == UIGestureRecognizerStateBegan){
        prevPanPoint = [pan locationInView:self.view.superview];
    }
 
    CGPoint curr = [pan locationInView:self.view.superview];
 
	float diffx = curr.x - prevPanPoint.x;
	float diffy = curr.y - prevPanPoint.y;
 
	CGPoint centre = self.view.center;
	centre.x += diffx;
	centre.y += diffy;
	self.view.center = centre;
 
    prevPanPoint = curr;
}
 
-(void)tappedGestureAction:(UITapGestureRecognizer *)tap{
    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"View Tapped" message:@"Tapped" delegate:nil cancelButtonTitle:@"Dissmiss" otherButtonTitles:@"Done", nil];
    [av show];
}

For the full code demo you can download my GesturesDemo here.

Resources