Animations in iOS are easy, except when they’re not. I learned this the hard way making SKBounceAnimation
, when I learned about how explicit animations are so different and weird compared to implicit animations.
Today, I learned a new lesson. You would think something like
mySublayer.cornerRadius = 3;
myView.frame = CGRectMake(0, 0, 100, 100);
[UIView animateWithDuration:0.25 animations:^{
mySublayer.cornerRadius = 5;
myView.frame = CGRectMake(50, 50, 100, 100);
}];
would just work. But apparently you can’t perform sublayer animations in an animateWithDuration:
block, so your CALayer
just picks its own duration and timing function, and animates it anyway. This can be a subtle effect, but if you flip the Toggle Slow Animations
flag in the Simulator, it becomes super obvious, since CATransactions
aren’t affected by that menu item.
The solution is to create a separate CATransaction
mySublayer.cornerRadius = 3;
myView.frame = CGRectMake(0, 0, 100, 100);
CGFloat duration = 0.18f;
[CATransaction begin];
[CATransaction setAnimationDuration:duration];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut] ];
mySublayer.cornerRadius = 5;
[CATransaction commit];
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationCurveEaseInOut animations:^{
myView.frame = CGRectMake(50, 50, 100, 100);
} completion:^(BOOL finished) { }];
Your CATransaction can be inside your animations
block if you like. Apple warns that
This type of mixing should not be used in situations where precise timing is needed.
but it looks pretty dead-on to me. The only information about doing this kind of thing is found in three paragraphs on the Apple documentation site, found here.