Simple Strategies for Smooth Animation on the iPhone
The iPhone was revolutionary for its use of direct manipulation – the feeling that you’re really holding content in your hands and manipulating it with your fingertips. While many mobile platforms have touch, it is the realistic physics and fluid animation of the iPhone that sets it apart from its competitors.
However, jerky scrolling ruins the experience. The new UI of Twitter for iPhone 4.0 contains many details that could impact performance, so we had to treat 60 frame-per-second animation as a priority. If you are troubleshooting animation performance, this post should provide some useful pointers.
A review of layers
Animation on iOS is powered by Core Animation layers. Layers are a simple abstraction for working with the GPU. When animating layers, the GPU just transforms surfaces as an extended function of the hardware itself. However, the GPU is not optimized for drawing. Everything in your view’s drawRect:
is handled by the CPU, then handed off to the GPU as a texture.
Animation problems fall into one of those two phases in the pipeline. Either the GPU is being taxed by expensive operations, or the CPU is spending too much time preparing the cell before handing it off to the GPU. The following sections contain simple directives, based on how we addressed each of these challenges.
GPU bottlenecks
When the GPU is overburdened, it manifests with low, but consistent, framerates. The most common reasons may be excessive compositing, blending, or pixel misalignment. Consider the following Tweet:
Use direct drawing
A naive implementation of a Tweet cell might include a UILabel
for the username, a UILabel
for the tweet text, a UIImageView
for the avatar, and so on.
Unfortunately, each view burdens Core Animation with extra compositing.
Instead, our Tweet cells contain a single view with no subviews; a single drawRect:
draws everything.
We institutionalized direct drawing by creating a generic table view cell class that accepts a block for its drawRect:
method. This is, by far, the most commonly used cell in the app....