views:

38

answers:

2

I have a CALayer object. In viewDidLoad: I set a transform to it using layer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI/8.0, 0, 0, 1); This works.

After loading, I apply a CAKeyframeAnimation to animate the rotation of that layer. It also works and animation finishes correctly. To prevent the layer from removing the animation after completion I use

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

All of this works fine. But a problem occurs when I try to change the transform again (without animation) layer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI/8.0, 0, 0, 1);. Nothing happens. Layer doesn't change its transform to what I have specified. If I run the animation again, the animation will happen. But cannot change the transform property without animation.

Any help is appreciated..

A: 

First of all, why are you avoiding removing the animation upon completion? You don't need these two lines,

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

since you are actually setting the layer's transform property. Those two lines are what you would use if all you wanted was the final visual state after the animation while keeping the transform the same as the original (which frankly I've never had a use for).

The next thing you have to realize is that you are setting the transform to the same value twice. Setting the transform on a layer is not additive by default. What I mean is that while you are expecting it to take your first transform and concatenating the same transform again from the final transform state, it doesn't work that way with the code you're using. You won't see a change because you're setting the state to the state it already has.

I haven't tried it, but I think that you could probably take the first transform and concatenate the new one. Something like:

layer.transform = CATransform3DRotate(layer.transform, M_PI/8.0, 0, 0, 1);

Notice how I'm starting from the current transform on the layer (first parameter of CATransform3DRotate), instead of identity. Give that a try. If it doesn't work, try something like:

layer.transform = CATransform3DConcat(layer.transform, 
                             CATransform3DMakeRotation(M_PI/8.0, 0, 0, 1));
Matt Long
Well, I need the final visual state (after animation) to remain, until I set it to a new value manually later on. That's why I set removedOnCompletion=NO;I know about transforms and concatenating them, but even if I set the transform to a different value (other than M_PI/8.0) after animation it doesn't reflect visually. It seems as if the layer's visual state gets locked after the animation with my current code.I think I'll hv to avoid using removedOnCompletion stuff and go with manually setting the layer.transform in animationDidStop. I don't know whether it works. I'll try and post here.
ravinsp
A: 

OK, I managed to get this working. What I did was setting the layer.tranform just after calling [layer addAnimation:]. In that way, after the animation is finished, the layer will stay in the desired position as it is. Here is my code:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.repeatCount = 1;
animation.duration = 3.0;
animation.fromValue = [NSNumber numberWithDouble:currentRotationAngle];
animation.toValue = [NSNumber numberWithDouble:newRotationAngle];

[layer addAnimation:animation forKey:@"rotationAnimation"];
[layer setAffineTransform:CGAffineTransformMakeRotation(newRotationAngle)];

The problem I had was using 'layer.removedOnCompletion' and 'layer.fillemode'. I don't have to use them. In the new way the layer will display the layer using the layer.transform after animation is complete. CAAnimations only update the layer's presentationLayer (which maintains the layer's visual state) while animating. When the animation is finished, it will revert the layer's visual state to the one imposed by layer.transform.

ravinsp