可直接操作的使用的iPhone - 你真的拿在手里,并用指尖操纵它的感觉是革命性的。虽然许多移动平台有触摸功能,这是iphone现实物理和流畅的动画,使它区别于它的竞争对手。
然而,糟糕的滚动毁掉了体验。Twitter针对iphone 4.0的新UI包含了许多可能影响性能的细节,所以我们不得不以处理60帧每秒的动画为优先。如果您正发现并排除动画性能,这个帖子应该可以提供一些有用的建议。
层的检查
动画在iOS上是由Core Animation层推动的。层是一个跟GPU一起工作的简单抽象。当层运动,GPU只是作为一个硬件本身的扩展功能变换了表层。然而GPU不会为绘制优化。你view里drawRect: 方法里的所有东西都被CPU处理,然后作为纹理传递给GPU。
动画问题陷入在管道中的两个阶段。无论是GPU负担昂贵的操作,或者是CPU在交到GPU之前花费太多时间去准备cell。下面的章节包含简单的指令,基于我们如何解决这些挑战。
GPU的瓶颈
当GPU负担过重,表现低,但帧率一致。最常见的原因可能是过度合成,混合,或像素错位。考虑下面的Tweet:
一个单纯的Tweet cell实现可能包含一个 UILabel
作为用户名, 一个 UILabel
作为tweet的文字, 一个 UIImageView
作为头像, 等等。
不幸的是,每一个视图要负担Core Animation额外的合成。
相反,我们的tweet cell含有一个没有子视图的单一视图;一个单一的drawRect:
绘制所有。
我们通过创建一个通用的table view cell类制度化地直接绘制,来为 drawRect:
方法接受一个block。这是,到目前为止,在应用程序中最常用的cell。
避免混合
你会注意到Tweets在iPhone 4上的纹理背景的上面有一个垂下的阴影。这表现是一个挑战,作为混合是昂贵的。
我们通过减少Core Animation不得不考虑的非不透明的面积,从cell的内容区域上分离阴影区域来解决这个问题。
为了快速发现混合,可以选择Core Animation instrument里Instruments下的 Color Blended Layers选项。绿色区域表示不透明;红色区指示出混合的表面。
检查像素对齐
发现以下代码中的危险点:
CGRect subframe = CGRectMake(x, y, width / 2.0, height / 2.0);
如果宽度是奇数,则subFrame将有一个分数的宽度。Core Animation将接受这一点,但它需要反锯齿处理,这是昂贵的。相反,运行floor 或 ceil 计算值。
在Instruments下,检查Color Misaligned Images,寻找偶然的反锯齿处理。
cell准备的瓶颈
动画第二类问题称为“pop”并且发生在新的cell滚动进入视图。当一个cell即将出现在屏幕上,在drop一个框架之前它只有17毫秒来提供内容。
循环利用cell
如table view文档中的描述,无论何时他们出现或消失,你应该循环利用cell在
dequeueReusableCellWithIdentifier:
的帮助下,而不是创建和销毁cell对象。
drawRect:
如果你是直接绘制和循环利用cell,你仍然会看到一个pop,检查你drawRect: 的时间:Instruments下的Core Animation。如果需要,消除“nice to have”细节,如敏感的坡度。
如果必要的话请预渲染
有时,你不能简化绘制。 iPhone 4.0 Twitter中的新的#Discover tab在cell中显示大图。不管多么简单的处理,缩放和裁剪一个大的图像是昂贵的。
我们知道#Discover有一个十个story的上限,所以我们决定交换CPU的内存。当我们收到一个热门story图片我们先对低优先级背景队列的cell预渲染,并将其存储在cache中。当cell滚入视图,我们设置cell的layer.contents对预焙CGImage,不需要绘制。
结论
所有的这些优化的代价是代码的复杂性和开发人员的生产力。只要你不让自己陷入一个建筑的角落,你可以经常在你写的最简单的东西工作了,并收集硬件的实际测量数据之后应用这些优化的事。
记住:过早优化是万恶之源。