CPU 负责计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。随后 CPU 会将计算好的内容提交到 GPU 去,由 GPU 进行变换、合成、渲染。CPU和GPU任一阻碍流程,都会造成掉帧现象,从而卡顿。所以优化主要集中在减少CPU的计算和GPU的渲染。
-
UIView 持有 CALayer 用于显示,View 中大部分显示属性实际是从 Layer 映射而来;Layer 的 delegate 在这里是 View,当其属性改变、动画产生时,View 能够得到通知。UIView 和 CALayer 不是线程安全的,并且只能在主线程创建、访问和销毁。对于不需要响应触摸事件的控件,用CALayer会更加轻量。
-
避免对UIView使用透明。(UIView默认是非透明)。原因是透明对性能要求较高,如果在滚动时页面比较复杂,体验上的差异会相对明显。UIView的背景色避免使用clearColor
-
减少视图或者layer的层级数量,在有多个层级时,可以将多图合并成一张图,再渲染显示。
-
避免图像融合,不透明的视图显示设置opaque属性为YES,避免alpha通道合成;
-
避免离屏渲染,CALayer的 border、圆角、阴影、遮罩mask,CASharpLayer的矢量图形显示,通常会触发离屏渲染(offscreen rendering),而离屏渲染通常发生在 GPU 中。
-
将绘制图像放在子线程中执行,如在子线程中使用 CGContext进行画图,在主线程中 layer.contents = img。(针对显示单张图片,不需进行交互的时候)
-
当GPU 资源已经占满,而 CPU 资源消耗很少时,可适当使用Rasterize(光栅栏),但这会把原本离屏渲染的操作转嫁到 CPU 上去。比如出现大量圆角的 CALayer,并且快速滑动时,最彻底的解决办法,就是把需要显示的图形在后台线程绘制为图片,避免使用圆角、阴影、遮罩等属性。
-
避免过于庞大的xib。随着视图数量的增长,Autolayout 带来的 CPU 消耗会呈指数级上升
-
使图片符合UIImageView的尺寸。不要在运行的时候再让UIImageView自行压缩,因为这样会降低运行时的性能。(注:手动压缩图片的方法,在context中使用drawInRect)
-
设置UIView的背景图片时,如果是整幅图,就采用addSubView一个UIImageView;如果是要重复平铺一个小图,就使用colorWithPatternImage,因为这个函数的设计上就是针对小图的,如果用于整幅大图来做背景,反而会消耗更多内存。
-
对于重复使用的图片使用imageNamed:来创建(这个会缓存),对于不需重复使用的,使用imageWithContentsOfFile。
-
UITableView的高度有时候会根据内容来自动计算,这种情况比较消耗资源。如果明知有哪几种高度的话,就将高度缓存重用;尽量不要在 cellForRowAtIndexPath:方法中做很多事情。不仅仅重用cell,对于section的header和footer也进行重用。推荐优化UITableViewCell高度计算的那些事
-
选择合适的collection。 如:Array使用下标查找较快,但插入和删除较慢。set进行插入和删除很快。
-
对常用的东西进行缓存。如从网上下载的需要经常显示的图片(这个在许多第三方框架如SDWebImage中都已经使用了)。对于一些下载下来,明显不需要访问网络再获取的图片,可以直接为其制造一个NSURLRequest,并使这个NSURLRequest仅从缓存读取数据。对于另外一些不涉及HTTP请求地址的数据,可以通过NSCache进行缓存。
-
重用一些高消耗的对象,如NSDateFormatter、NSCalender等。解决方法:可以将其作为property、甚至是静态变量作为单例在APP中使用。并且,NSDateFormatter的 setDateFormate也是非常消耗资源的一个操作。
-
对于排版复杂的文字或者图文混排,使用CoreText技术。(而不是一味地堆UILabel)
-
在对渲染的效率要求较高的页面中,避免使用UILabel、UITextView等在主线程中进行排版和绘制的控件。应自定义文本控件,用TextKit或者CoreText进行文本异步绘制。另外,还有facebook的AsyncDisplayKit框架可以采用。
网友评论