代码改变世界

ios上的绘制优化

2011-11-28 17:45  ianwang  阅读(1622)  评论(0编辑  收藏  举报

Improving Image Drawing Performance on iOS 

这篇apple官方的文档说明了一些动画绘制原则以及预渲染技术。简要总结如下:

1.尽量避免频繁调用-drawrect:

  这是相当耗时的操作,因为 UIView作为单个元素,无论是局部(setNeedsDisplayInRect)或者是整体(setNeedsDisplay)发出重绘,整个view都会被更新到屏幕上(iPhone/ipad的刷屏方式决定的)。

2.尽量使用UIView/CALayer实现一些动画,不要试图通过发出绘制消息来实现动画。

     对于图片动画来说,把图片封装到UIImageView就可以完成旋转,平移,缩放,甚至多帧动画。(通过UIImageView的animationImage这个属性)

3.若UIView中存在需要时常更新的部分,建议分割这个UIView,划分为几个subview/Layer单独绘制

    这样做的好处有三点:

    一. 因为绘制独立减少了主view绘制次数,

           二. 不会因为一些小的部件的更新导致整个场景被重绘(UIView/Layer 见1的说明)

           三. 主场景中某些部分的更新可能只是位置的改变,若对这些部分进行单独UIview/CALayer的处理,就可以避免发出drawrect。

    这在游戏场景中可能经常需要用到,所以iphone游戏的sprite就应当是个CALayer,总体的设计思想:独立各个部分的绘制,降低他们的绘制上的关联性

4.对于图片,应该避免缩放处理,若涉及到解压缩和缩放,应该对其预处理得到新的UIImage保存下来。

         特别是在iPhone4上由于分辨率很大,缩放绘制是个很耗时的操作。现贴上相关code(来自上述的apple文档):

 1 - (UIImage*)resizeImage:(UIImage*)image toWidth:(NSInteger)width height:(NSInteger)height
2 {
3 // Create a graphics context with the target size
4 // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
5 // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
6 CGSize size = CGSizeMake(width, height);
7 if (NULL != UIGraphicsBeginImageContextWithOptions)
8 UIGraphicsBeginImageContextWithOptions(size, NO, 0);
9 else
10 UIGraphicsBeginImageContext(size);
11
12 CGContextRef context = UIGraphicsGetCurrentContext();
13
14 // Flip the context because UIKit coordinate system is upside down to Quartz coordinate system
15 CGContextTranslateCTM(context, 0.0, height);
16 CGContextScaleCTM(context, 1.0, -1.0);
17
18 // Draw the original image to the context
19 CGContextSetBlendMode(context, kCGBlendModeCopy);
20 CGContextDrawImage(context, CGRectMake(0.0, 0.0, width, height), image.CGImage);
21
22 // Retrieve the UIImage from the current context
23 UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
24
25 UIGraphicsEndImageContext();
26
27 return imageOut;
28 }