Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When exactly do implicit animations take place in iOS?

Everyone and every book claims that there are implicit animations happening in CALayer. However, every time I wanted to verify that so far, I end up with a hard-snap to the set value. No animation at all.

Here's an example in a project where nothing else is happening. All I do is create a view, then get it's CALayer instance and do something that should be implicitly animated.

[theLayer setValue:[NSNumber numberWithFloat:M_PI * 1.1] forKeyPath:@"transform.rotation.z"];

Another one:

CGRect currentBounds = theLayer.bounds;
currentBounds.size.width += 120.f;
[self.animatedLayer setBounds:currentBounds];

The view contains some stuff of course so I can see the change. I see the visual change, but as a hard snap. No animation at all.

So either all those books are wrong and have old Mac OS X knowledge in mind when writing about Core Animation and implicit animations, or I'm doing something wrong. Can anyone provide an working example that demonstrates implicit animations on the iPhone?

like image 791
Proud Member Avatar asked Jan 20 '11 15:01

Proud Member


4 Answers

UIKit disables implicit animations. To be more specific, a CALayer associated with a UIView will never implicitly animate. CALayers that you create yourself and that are not associated with a UIView will buy into the normal implicit animation machinery.

If you're interested in how this works, implicit animations happen after the normal -actionForKey: lookup. If there's a CAAction for a given property, it's used. Otherwise, the implicit animation is used. In the case of a CALayer associated with a UIView, UIView implements the -actionForLayer:forKey: delegate method, and when not in a UIView animation block it always returns [NSNull null] to signify that the action lookup should stop here. This prevents implicit animations from working. Inside of a UIView animation block, it constructs its own action to represent the current UIView animation settings. Again, this prevents implicit animations.

If you need to animate CALayer properties that UIView won't do for you, you can use an explicit CAAnimation subclass (such as CABasicAnimation).

like image 63
Lily Ballard Avatar answered Nov 12 '22 20:11

Lily Ballard


Old post, but link below points to a section in the Core Animation Programming Guide that helps shed some more light on what Kevin Ballard was saying. There really needs to be a blatant note that mentions that in order to animate a UIView's underlying layer properties you need to ensure that you set the layer's delegate to an instance that will adopt the "actionForLayer:ForKey:" method and return nil. It's been found that you can also set the delegate to an instance that doesn't adopt this method and it still allows implicit animations, but this is a sloppy and confusing practice.

Core Animation - Layer Actions - Defined Search Pattern for Action Keys

like image 42
JonnyB Avatar answered Nov 12 '22 22:11

JonnyB


Keep in mind that sublayers of a UIView's primary layer do not normally have the UIView as their delegate. Therefore, they participate in implicit animation unless you explicitly block this, even if you haven't provided a delegate to return a nil action in response to actionForLayer:forKey:.

So, one simple way to get implicit animation in a generic view is simply to add a sublayer that covers the primary layer.

Matt Neuberg's book Programming iOS 5 (currently in beta on Safari Books Online) explains this topic very lucidly.

like image 1
GSnyder Avatar answered Nov 12 '22 22:11

GSnyder


It's exactly correct of Kevin Ballard's answer. I want to provide something more here.

The detail information from the official document

There is a section called: Rules for Modifying Layers in iOS, and you will find

The UIView class disables layer animations by default but reenables them inside animation blocks.

Except enable the implicit in the UIView animation block. There are two another solution:

  1. Make the layer you need animation a sublayer of a view. Refer to the [answer][2]

    [2]: Implicit property animations do not work with CAReplicatorLayer? of Implicit animation fade-in is not working. I tried this, it worked as expected.

  2. assign the layer's delegate to the layer itself. The default delegate of the layer in iOS is its backing store view which implements the actionForLayer:(id)layer forKey:(NSString *)key and return [NSNull null] to disable the implicit animation of the layer.
like image 1
Danyun Liu Avatar answered Nov 12 '22 21:11

Danyun Liu