views:

343

answers:

2

Example from Mac OS X:

[[aView animator] setFrame:NSMakeRect(100.0,100.0,300.0,300.0)];

I have tried something similar in UIKit, but it seems the animator method is not there for UIView. So there's no "implicit" animation?

+5  A: 

The iPhone supports implicit animation, though it does not use an animator object, it is built directly into UIView. Try this instead:

[UIView beginAnimations:nil context:nil];
[aView setFrame:NSMakeRect(100.0,100.0,300.0,300.0)];
[UIView commitAnimations];

The exact details are documented here.

Every view is always layer backed as well, so you don;t have to turn on layers in order to get a layer for explicit animation.

Louis Gerbarg
wouldn't this one be an explicit animation? or what's the difference there?
Thanks
No. Explicit animation is when you directly use CoreAnimation and attach CAAnimations to layers. Implicit animation is when you set some parameters about an animation, but otherwise just set normal properties on the view and let the system animate those changes for you. On the desktop implicit animation is done by forwarding all your NSView through a proxy, on the UIView knows how to handle it without using a proxy, you just have to tell it you want it to construct the implicit animations through a class method.
Louis Gerbarg
+2  A: 

Turns out iPhone OS does indeed support implicit animations on CALayer as defined in the Core Animation Programming Guide from Apple. On Mac OS X, a layer becomes animatable when it backs an NSView by setting:

[view setWantsLayer:YES];

On iPhone OS, simply set the layer delegate to the UIViewController-derived class that hosts the UIView-derived object you would like to animate. For example, if you have a property defined for a UILabel called label, inside of the UIViewController-derived class that hosts it, the code would look something like this (an example of an event handler for a UIButton Touch Up Inside event):

-(void) buttonPressedToAnimateTheLabel:(id)sender
{
    CALayer *labelLayer = self.label.layer;

    labelLayer.delegate = self;

    layer.position = CGPointMake(labelLayer.position.x, labelLayer.position.y + 50);
}

The label will then animate in the exact same manner as it would on Mac OS X just by changing the position.

Some notes about this:

  1. it is definitely the UIViewController that is the delegate, not the UIView. Making a UIView the delegate causes the app to blow up.

  2. the delegate needs to be set in a method called after the UIViewController-derived class has completely finished loading, i.e. in an event handler for a control hosted by the class. I tried adding it in initWithNibName:bundle:, awakeFromNib, viewDidLoad, and viewWillAppear:animated and it did not work. Setting the delegate in the first two methods caused the label not to animate; it just changed positions immediately. Adding it in the last two caused the label to disappear altogether.

  3. after the delegate is set once in an event handler, it will be good for the remainder of the lifetime of the UIViewController-derived class. Changing the layer properties in other event handlers will cause them to animate without setting the delegate for the layer again.

  4. when the UIViewController-derived class loses focus, the delegate must be set to nil in the viewWillDisappear:animated method, or else the application will blow up

There must be some place to set the delegate one time only so it isn't set multiple times as a result of a event handler being called, but I have yet to find that place. At least it works this way and setting it multiple times as a result of the event handler being called multiple times seems harmless enough.

It would certainly be nice if this was all documented in the Core Animation Programming Guide. I spent days trying to figure this out! Hope this saves all the trouble of hunting it down!

justinkmunger
I was having the same problem with the layer not animating (just jumping) until I added the delegate. However I am (at least with 3.2 on the iPad) able to set the delegate in the viewDidLoad() method and it works alright.
Pat Niemeyer