一、CPU 资源消耗原因和解决方案
1、对象创建,尽量使用轻量的对象代替重量的对象,例如用CALayer代替UIView
2、对象调整,尽量减少不必要的UI属性修改
3、对象销毁,可以异步放到后台线程去销毁
4、布局计算,尽量提前计算好布局,最好一次性调整好对应属性
5、Autolayout,在复杂布局时尽量少使用Autolayout
6、文本计算,参考UILabel内部的计算方式,在后台线程用[NSAttributedString boundingRectWithSize:options:context:] 来计算文本宽高,用 -[NSAttributedString drawWithRect:options:context:] 来绘制文本
7、文本渲染,可以自定义控件,用 TextKit 或最底层的 CoreText 对文本异步绘制
8、图片的解码,在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片
9、图像的绘制,图像的绘制通常是指用那些以 CG 开头的方法把图像绘制到画布中,然后从画布创建图片并显示这样一个过程,这个过程可以放到后台线程进行
二、GPU 资源消耗原因和解决方案
GPU 处理的事情:接收提交的纹理(Texture)和顶点描述(三角形),应用变换(transform)、混合并渲染,然后输出到屏幕上。
1、纹理的渲染
2、视图的混合,view的opaque属性设置成YES
3、图形的生成,把需要显示的图形在后台线程绘制为图片,避免使用圆角、阴影、遮罩等属性
1、预排版
从接口获取数据转成model之后,先在后头线程算好各个控件应该显示的frame及cell的高度,封装成CellLayout对象。在tableview执行代理方法时直接取出数据布局,甚至可以把CellLayout对象缓存进内存中,这样用户滚动tableview时可以最大程度的提高性能。
2、预渲染
cell内容的离屏渲染会造成较大的GPU消耗,当要使用到Layer 的 border、corner、shadow、mask 等方法时,可以在后台线程预渲染,然后单独缓存到图片缓存的队列中去
- (UIImage *)imageWithCornerRadius:(CGFloat)radius {
CGRect rect = (CGRect){0.f, 0.f, self.size};
UIGraphicsBeginImageContextWithOptions(self.size, NO, UIScreen.mainScreen.scale);
CGContextAddPath(UIGraphicsGetCurrentContext(),
[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius].CGPath);
CGContextClip(UIGraphicsGetCurrentContext());
[self drawInRect:rect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
3、异步绘制
4、全局并发控制
3、更高效的异步图片加载
UIImageView相对UIView来说会带来额外的性能消耗,如果对性能有严格的要求,可以使用UIView.layer.contents来代替UIImageView,为此可以为CALayer加上setImageWithURL:方法。
4、进一步优化性能
减少view上图层的数量,用CALayer代替UIView,
将cell按类型划分,减少不必要的视图对象和操作,
5、检测性能的工具
FPS 指示器 YYFPSLabel 可以监测当前页面的帧数。
MLeaksFinder 可以检测内存泄露
网友评论