Archive for September, 2010

Core Animation using blocks

7

Previously I have written a blog post about doing simple animations with UIViews, which you can find here. Starting in iOS 4.0 you can now do this with blocks.

Blocks have two major benefits (although there are more):

  • They can be used in conjunction with Grand Central Dispatch (GCD), as an alternative to threading.
  • They can be used for callbacks, instead of NSNotifications, callback selectors, function pointers etc. This is usually done by providing a callback/completion block, and this is what we will be looking at here.

The most common method that you will use to animate views using blocks, is the following class method on UIView:

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

This method allows you to set a time interval, along with an animations block and a completion block.

Lets say we have a UIView variable called redView.

redView = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,320)];
redView.backgroundColor = [UIColor redColor];

We will then add redView as a subview of the view controller’s view

[self.view addSubview:redView];

A common situation you may find your self in, is when you finish animating a view (e.g. changing its alpha), you would then want to remove it from it’s superview, and then release it from memory.

So if you had (for example) a method called animate to trigger off the animation, you would need to add an “animation did stop selector” to the animation. In the following example I have called it cleanUp.

- (void)animate{
 
   [UIView beginAnimations:@"" context:NULL];
   [UIView setAnimationDuration:5.0];
   [UIView setAnimationDidStopSelector:@selector(cleanUp)];
   [redView setAlpha:0.0];
   [UIView commitAnimations];
 
}
 
- (void)cleanUp{
 
    [redView removeFromSuperview];
    //I do release and = nil on the same line as a coding convention
    //so I don't forget to "nil" the variable
    [redView release], redView = nil;	
}

Although this works well enough, it does mean that your code is split up into the animation code and the (completion) clean up code. If you end up doing this a lot, your code can end up becoming very fragmented and hard to follow.

Using blocks we can do the following:

- (void)animate{
 
[UIView animateWithDuration:5.0
 
                            animations:^{ 
	                          redView.alpha = 0.0; 
	                     }
 
                           completion:^(BOOL  completed){
	                          [redView removeFromSuperview];
                                  [redView release],redView = nil;
	                    }
 ];
 
 
}

This keeps things nice and simple, and it means that you can easily see what code will be executed when the animation completes.

All of the animations you wish to do are passed in using a block:

 
^{ 
redView.alpha = 0.0; 
}

This block takes no arguments, and it also does not have a return type (so it defaults to void).

Instead of calling the cleanUp selector, we can simply pass in a completion block:

 
^(BOOL  completed){
[redView removeFromSuperview];
[redView release],redView = nil;
}

This block takes one parameter, which is a bool signifying if the animation has completed when the block is executed. In this example we ignore the completed variable, and we assume that the animation has completed for simplicity reasons. In the body of the block we do same as we did in the cleanUp selector, we remove redView from its super view and then release it from memory.

In some situations you won’t need to use blocks for Core Animation, but when you do, you will find it cleans up your code no end.

Apple’s Master Plan

0

There is a theme coming from Cupertino, which was made slightly more apparent yesterday when they removed storage from the Apple TV … the master plan.

Apple are clearly going for the “your family has one master computer, and you sync lots of (smaller/lower cost) devices with it” distribution model … all of these devices are available from Apple. iPads are replacing laptops (for some), and people have long bought into the iPod revolution to play there digital media on the move. The AppleTV is a bit different as you can stream rented content from Apple to it, but the only way to get your own content on it, is to stream it from another device. This would ether be from your computer, or an iOS device which you have already synced with your computer.

Although “the cloud” is clearly the future, it isn’t yet ready for prime time. Until everyone in their normal every day lives has access to a (constant) high speed internet connection, the cloud is merely a pipe dream in terms of using it for all of your data driven tasks.

Don’t get me wrong, the clouds time will come, but in the next 5 years ? … I’m not so sure.

At the moment client applications (native applications that sync with a server and then cache the data for offline use), are the correct implementation for the the moment. As far as streaming movies go, Apple knows that all AppleTVs will live in a home, and therefore (hopefully) have the bandwidth required to play HD footage.

Although people will disagree, the master plan is probably the right choice for the start of this decade, but the cloud’s time will come.

Go to Top