Core Animation for Mac OS X and the IPhone

Bill Dudney

Mentioned 6

Describes how to use Core Animation to enhance Cocoa applications, covering such topics as layer-backed views, layers in 3D, media layers, and layer scrolling and geometry.

More on Amazon.com

Mentioned in questions and answers.

I am relatively new to iPhone programming, and I have a considerably complex app to develop.
This app requires animations such as burning a photo, flushing something down a toilet, etc.

Is there any way I can manage to code these animations without having to learn OpenGL ES?

IMO this book is the leading book reference on Core Animation and they walk through some pretty impressive/complex animations: http://www.amazon.com/Core-Animation-Mac-iPhone-Programmers/dp/1934356107/ref=sr_1_2?ie=UTF8&s=books&qid=1264529803&sr=8-2-spell

Possibly you get do what you need with some crafty coding.

I'm having a fundamental issue with use of drawRect: Any advice would be greatly appreciated.

The application needs to draw a variety of .png images at different times, sometimes with animation, sometimes without.

A design goal that I was hoping to adhere to is to have the code inside drawRect: very simple and "dumb" - i.e. just do drawing and no other application logic.

To draw the image I am using the drawAtPoint: method of UIImage. Since this method does not take a CGContext as a parameter, it can only be called within the drawRect: method. So I have:

- (void)drawRect:(CGRect)rect {

 [firstImage drawAtPoint:CGPointMake(firstOffsetX, firstOffsetY)];

}

All fine and dandy for one image. To draw multiple images (over time) the approach I have taken is to maintain an array of dictionaries with each dictionary containing an image, the point location to draw at and a flag to enable/suppress drawing for that image. I add dictionaries to the array over time and trigger drawing via the setNeedsDisplay: method of UIView. Use of an array of dictionaries allows me to completely reconstruct the entire display at any time. drawRect: now becomes:

- (void)drawRect:(CGRect)rect {


 for (NSMutableDictionary *imageDict in [self imageDisplayList]) {
  if ([[imageDict objectForKey:@"needsDisplay"] boolValue]) {
   [[imageDict objectForKey:@"image"] drawAtPoint:[[imageDict objectForKey:@"location"] CGPointValue]];
   [imageDict setValue:[NSNumber numberWithBool:NO] forKey:@"needsDisplay"];
  }
 }
}

Still OK. The code is simple and compact. Animating this is where I run into problems. The first problem is where do I put the animation code? Do I put it in UIView or UIViewController? If in UIView, do I put it in drawRect: or elsewhere? Because the actual animation depends on the overall state of the application, I would need nested switch statements which, if put in drawRect:, would look something like this:

- (void)drawRect:(CGRect)rect {

 for (NSMutableDictionary *imageDict in [self imageDisplayList]) {
  if ([[imageDict objectForKey:@"needsDisplay"] boolValue]) {

   switch ([self currentState]) {
    case STATE_1:
     switch ([[imageDict objectForKey:@"animationID"] intValue]) {
      case ANIMATE_FADE_IN:
       [self setAlpha:0.0];
       [UIView beginAnimations:[[imageDict objectForKey:@"animationID"] intValue] context:nil];
       [UIView setAnimationDelegate:self];
       [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
       [UIView setAnimationDuration:2];
       [self setAlpha:1.0];
       break;
      case ANIMATE_FADE_OUT:
       [self setAlpha:1.0];
       [UIView beginAnimations:[[imageDict objectForKey:@"animationID"] intValue] context:nil];
       [UIView setAnimationDelegate:self];
       [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
       [UIView setAnimationDuration:2];
       [self setAlpha:0.0];
       break;
      case ANIMATE_OTHER:
       // similar code here
       break;
      default:
       break;
     }
     break;
    case STATE_2:
     // similar code here
     break;
    default:
     break;
   }
   [[imageDict objectForKey:@"image"] drawAtPoint:[[imageDict objectForKey:@"location"] CGPointValue]];
   [imageDict setValue:[NSNumber numberWithBool:NO] forKey:@"needsDisplay"];
  }
 }

 [UIView commitAnimations];

}

In addition, to make multiple sequential animations work correctly, there would need to be an outer controlling mechanism involving the animation delegate animationDidStop: callback that would set the needsDisplay entries in the dictionaries to allow/suppress drawing (and animation).

The point that we are at now is that it all starts to look very ugly. More specifically:

  • drawRect: starts to bloat quickly and contain code that is not "just drawing" code
  • the UIView needs implicit awareness of the application state
  • the overall process of drawing is now spread across three methods at a minimum

And on to the point of this post: how can I do this better? What would the experts out there recommend in terms of overall structure? How can I keep application state information out of the view? Am I looking at this problem from the wrong direction. Is there some completely different approach that I should consider?

I'd start off by not re-inventing Core Animation

Bill Dudney's is probably the best: Core Animation for Mac OS X and the iPhone: Creating Compelling Dynamic User Interfaces

I am developing an iPhone version of this game. http://www.students.uni-mainz.de/rathb000/Fillit/Game.html

I am using an NSTimer to change the position of the ship by 1 pixel and the time interval for the timer is 0.002.

However, i have noticed that the ship doesnt move faster if i reduce the time interval furthur. Infact, there is no difference between 0.05 and 0.002. Is there is a restriction on the minimum time you have to give as NSTimeInterval?

The ship currently moves too slow for the game to be exciting.

Also, the movement of birds (which is also achieved by NSTimer) becomes slow when i press any button for moving the ship.

Any idea about how this can be solved?

NSTimer is not a real-time mechanism; it fires as part of the run loop and is not ideal for creating smooth, fluid animations. However, there is an SDK that is part of the iPhone OS called Core Animation - it provides a library of functions for performing smooth animation of layers and views. Here is a reasonably good series of video tutorials that you may find useful. There is also an excellent book called Core Animation for Mac OS X and iPhone that you may find useful.

There is also the core animation documentation from Apple that describes how to use the CABasicAnimation class to animate properties of any layer or view. Here is an example of an explicit layer animation from the docs:

CABasicAnimation *theAnimation; 

theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
theAnimation.duration=3.0;
theAnimation.repeatCount=1;
theAnimation.autoreverses=NO;
theAnimation.fromValue=CATransform3DTranslate(0,0,0);
theAnimation.toValue=CATransform3DTranslate(20,20,0);

[theLayer addAnimation:theAnimation forKey:@"animateTransform"];

I am fairly new to transition and animation methods in Iphone. Can somebody pl. guide me the basics of transition and Animation in Iphone. This is needed frequently in my Apps. Can anybody tell me any link where i can Understand ABC of animation ?

When it comes to Core Animation and UIView animations, you might want to look at Marcus Zarra and Matt Long's new book Core Animation: Simplified Animation Techniques for Mac and iPhone Development. It provides a very thorough walkthrough of Core Animation, from the high level UIView animations to more complex animations involving CALayers and CAAnimations. Bill Dudney also has an excellent Core Animation book.

As far as official documentation, the Core Animation Programming Guide is also well-written.

There are many questions here on Core Animation, tagged with core-animation.

Matt Gallagher has an interesting series of articles entitled "An Asteroids-style game in Core Animation".

Finally, I teach a course on iPhone development, in which I devoted a class to Core Animation and the neat things you can do in it. The course notes are available for download (VoodooPad format), and have quite a bit of detail in them, in addition to links to other resources and sample applications.

I'm looking to create simple animations (fades, windows sliding away, graphs moving or "filling up") in a Cocoa app I'm writing for OS X. I've tried finding information on Core Animation, Core Graphics, NSViewAnimation, and Quartz Composer and how to use these in a Cocoa app, but I'm quickly losing direction. There was also one source saying that Core Animation was no longer supported as of MountainLion. What should be used for basic animations? Is there a specific framework or third-party library that will be useful, or a best-practice method for animating productivity apps?

I apologize for not being more specific, but I'm a bit confused on what exactly to look up.

The simplest thing to do is to modify the properties of your view's layers. To do that, you need to set the flag for your views that says "wants layer" (I work mostly in iOS these days, so I forget exactly what it's called.) When you do that for a view, that view and all it's subviews are backed with CALayer objects.

Changes to animatable properties of layers are animated "implicitly" by default. You can also enclose changes to a layer's properties inside a CATransaction begin/end block to change things like the layer timing and animation curve.

The next step up in complexity is to create CAAnimation objects and add them to your layer. Start with CABasicAnimation. You should be able to find tutorials on the net that show you how to animate layer properties using CABasicAnimations.

The documentation is pretty thin, I'm afraid.

iOS adds a set of view animation methods that make animating views very easy. Sadly, there is no equivalent on Mac OS. You have to deal with animation proxies, which is kind of confusing. There are a couple of Core Animation books you might look into. One is by Marcus Zarra, and the other by Bill Dudney.

EDIT: Another option I didn't mention in my (rather old) post: Mac OS view objects have something called an animation proxy. You can send property changes to a view's animation proxy and the system creates an animation that makes that change.

If you're using auto-layout, beware that changing a view's frame or bounds doesn't work as expected because auto-layout tries to take over size and placement of your view objects. Instead, you want to add outlets to your constraints and animate changes to the settings of the constraints.

I want to learn "Core Animation" for the iOS not for the Mac.

Two books exist:

PragProg: Core Animation

AW: Core Animation Simplified

Have you read one of them (or both)? do you have a recommendation?

Thanks.

I haven't read either of the books you suggest.

I've read "Core Animation for Mac OS X and the iPhone" by Bill Dudney, and think that's a pretty good book.