iOS Recipes - Matt Drance [61]
ViewTransition/PRPViewTransition.m
- (void) SwitchLayers {
CALayer *oldLayer = [stripLayer.sublayers objectAtIndex:
numLayers-count-1];
CALayer * tLayer = [transform.sublayers objectAtIndex:layerNum];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
tLayer.contents = oldLayer.contents;
[oldLayer removeFromSuperlayer];
tLayer.contentsRect = CGRectMake(unitSize*(numLayers-count-1),
0, unitSize, 1);
[self animateLayers];
layerNum--;
if (layerNum < 0) layerNum = SIDES-1;
}
The animationDidStop delegate controls the sequence of turns of the tube, because it gradually “picks” up the layers of the backing image. At the end of the loop, we add an additional turn of the tube to make sure it is off the screen and then remove the tube from the view—its task complete.
ViewTransition/PRPViewTransition.m
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
if (count < numLayers) {
[self SwitchLayers];
} else if (count == numLayers) {
[self animateLayers];
} else { // Reached the end
[self removeFromSuperview];
}
}
To give the sample app a feel similar to a book-reading app, we use a UISwipeGestureRecognizer to trigger the transition, alternating between three sample images. All the hard work is done in the PRPViewTransition class, so the setup to implement it is quite simple. We create an instance of the class specifying the view to be transitioned and the number of images splits. We then set the duration of the transition and add it as a subview of the ViewController. Because the initializer of the transView has already made a copy of the original view, split into layers, we can now remove the original view from the viewController. The process of adding the view calls the didMoveToSuperview delegate and kicks off the transition animation.
ViewTransition/MainViewController.m
- (void)swiped:(UISwipeGestureRecognizer *)sender {
NSString *splashImage;
loop++;
switch (loop) {
case 1:
splashImage = @"settings.png";
break;
case 2:
splashImage = @"BackImage.jpg";
break;
default:
splashImage = @"Default.png";
loop = 0;
break;
}
UIImageView *newView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:splashImage]];
newView.userInteractionEnabled = YES;
newView.frame = self.view.bounds;
[self.view addSubview:newView];
PRPViewTransition *transView = [PRPViewTransition
viewWithView:self.currentView
splitInto:4];
transView.duration = 0.8;
[self.view addSubview:transView];
[self.currentView removeFromSuperview];
self.currentView = newView;
[newView release];
}
The final transition is a reasonable simulation of a page turn, though by adjusting the number of slices it’s also possible to create an effect closer to rolling the page away from the view. Currently the sample app works only in a single direction, but it shouldn’t be too difficult to implement the reverse of the process—to curl a page back over the current view.
Footnotes
[2] For more on how bezier curves work, check out the UIBezierPath section of the iPad Programming Guide on http://developer.apple.com.
[3] The Core Graphics libraries can create a radial, or circular, gradient, so there may be hope for the future.
Copyright © 2011, The Pragmatic Bookshelf.
Chapter 4
Networking Recipes
A great number of mobile apps rely on web services for their core experience. The iOS SDK gives you the tools to connect to just about any type of service you need but at a relatively low level. There are plenty of standard interactions and operations that every networked app needs to make, and many of them require more code than you might expect.
The recipes in this section illustrate some reusable solutions for a few of these common situations. They’re ready to use