I see several problems in your code.
First, you're grabbing the frame origin like this:
CGPoint point = CGPointMake(imView.frame.origin.x, imView.frame.origin.y);
Although it's not really a problem, you could simply do this:
CGPoint point = imView.frame.origin;
The problem is that you're setting the layer's position
to its frame's origin. But by default, the position controls the center of the view, and the frame's origin is its upper-left corner. You probably want to just pick up the layer's position in the first place:
CGPoint point = imView.layer.position; // equivalent to imView.center
Second, you're using the position.x
key path, which wants a CGFloat
value, but you're providing a CGPoint
value. This doesn't appear to cause a problem in the iOS 6.1 simulator, but it's probably a bad idea to assume it will always work.
Third, you need to understand that an animation does not change the properties of your layer! Each of the layers you normally manipulate (technically called a model layer) has an associated presentation layer. The presentation layer's properties control what is on the screen. When you change a model layer's property, Core Animation usually sets up an animation (from the old value to the new value) on the presentation layer automatically. This is called an implicit animation. A UIView
suppresses implicit animations on its layer.
When the animation on the presentation layer ends and is removed, the presentation layer's properties revert to its model layer's values. So to make the change permanent, you need to update the model layer's properties. Generally it's best to update the model layer's properties first, then add the animation, so that your explicit animation overwrites the implicit animation (if one was created).
As it happens, although you can animate position.x
, you need to set position
on the model
layer to make it stick. I tested this to work:
- (IBAction)perform:(id)sender {
CGPoint point0 = imView.layer.position;
CGPoint point1 = { point0.x + 50, point0.y };
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
anim.fromValue = @(point0.x);
anim.toValue = @(point1.x);
anim.duration = 1.5f;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
// First we update the model layer's property.
imView.layer.position = point1;
// Now we attach the animation.
[imView.layer addAnimation:anim forKey:@"position.x"];
}
(Note that I called my method perform:
. The method in the original post seems to be misspelled.)
If you want to really understand Core Animation, I highly recommend watching the Core Animation Essentials video from WWDC 2011. It's an hour long and contains a ton of useful information.