Graphics Reference
In-Depth Information
We can adjust the run loop mode of our animation timer so that it won't be delayed
by other events.
CADisplayLink
CADisplayLink is an NSTimer -like class provided by Core Animation that always fires
immediately prior to the screen being redrawn. Its interface is very similar to NSTimer , so it
is essentially a drop-in replacement, but instead of a timeInterval specified in seconds,
the CADisplayLink has an integer frameInterval property that specifies how many
frames to skip each time it fires. By default, this has a value of 1, meaning that it should fire
every frame. But if your animation code takes too long to reliably execute within a sixtieth
of a second, you can specify a frameInterval of 2, meaning that your animation will
update every other frame (30 frames per second) or 3, resulting in 20 frames per second,
and so on.
Using a CADisplayLink instead of an NSTimer will produce a smoother animation by
ensuring that the frame rate is as consistent as possible. But even CADisplayLink cannot
guarantee that every frame will happen on schedule. A stray task or an event outside of
your control (such as a resource-hungry background application) might still cause your
animation to occasionally skip frames. When using an NSTimer , the timer will simply fire
whenever it gets a chance, but CADisplayLink works differently: If it misses a scheduled
frame, it will skip it altogether and update at the next scheduled frame time.
Measuring Frame Duration
Regardless of whether we use an NSTimer or CADisplayLink , we still need to handle the
scenario where a frame takes longer to calculate than the expected time of one-sixtieth of a
second. Because we cannot know the actual frame duration in advance, we have to measure
it as it happens. We can do this by recording the time at the start of each frame using the
CACurrentMediaTime() function, and then comparing it to the time recorded for the
previous frame.
By comparing these times, we get an accurate frame duration measurement that we can use
in place of the hard-coded one-sixtieth value for our timing calculations. Let's update our
example with these improvements (see Listing 11.2).
Listing 11.2 Measuring Frame Duration for Smoother Animation
@interface ViewController ()
@property ( nonatomic , weak ) IBOutlet UIView *containerView;
@property ( nonatomic , strong ) UIImageView *ballView;
@property ( nonatomic , strong ) CADisplayLink *timer;
@property ( nonatomic , assign ) CFTimeInterval duration;
@property ( nonatomic , assign ) CFTimeInterval timeOffset;
Search WWH ::




Custom Search