Graphics Reference
In-Depth Information
- (
IBAction
)changeColor
{
//create a new random color
CGFloat
red =
arc4random
() / (
CGFloat
)
INT_MAX
;
CGFloat
green =
arc4random
() / (
CGFloat
)
INT_MAX
;
CGFloat
blue =
arc4random
() / (
CGFloat
)
INT_MAX
;
UIColor
*color = [
UIColor
colorWithRed
:red
green
:green
blue
:blue
alpha
:
1.0
];
//create a basic animation
CABasicAnimation
*animation = [
CABasicAnimation
animation
];
animation.
keyPath
=
@"backgroundColor"
;
animation.
toValue
= (
__bridge
id
)color.
CGColor
;
//apply animation without snap-back
[
self
applyBasicAnimation
:animation
toLayer
:
self
.
colorLayer
];
}
This simple implementation only handles animations with a
toValue
, not a
byValue
, but
it's a good start toward a general solution. You could package it up as a category method on
CALayer
to make it more convenient and reusable.
This might all seem like a lot of trouble to solve such a seemingly simple problem, but the
alternative is considerably
more
complex. If we don't update the target property
before
we
begin the animation, we cannot update it until after the animation has fully completed or we
will cancel the
CABasicAnimation
in progress. That means we need to update the property
at the exact point when the animation has finished, but before it gets removed from the
layer and the property snaps back to its original value. How can we determine that point?
CAAnimationDelegate
When using implicit animations in Chapter 7, we were able to detect when an animation
finished by using the
CATransaction
completion block. That approach isn't available when
using explicit animations, however, because the animation isn't associated with a
transaction.
To find out when an explicit animation has finished, we need to make use of the
animation's
delegate
property, which is an object conforming to the
CAAnimationDelegate
protocol.