iOS开发笔录iOS-深入UI

iOS开发:关于图形渲染以及界面优化的的一些想法

2017-06-10  本文已影响29人  高调的菜鸟

最近看了以下两篇文章,受益颇多,于是想把自己看完以后的一些想法写下来,理一理思路,如果有什么错误,欢迎各位指出。

绘制像素到屏幕上

iOS 保持界面流畅的技巧

首先,iOS上图形渲染分以下几种:

1、OnScreen Rendering(当前屏幕渲染,基于 GPU)

2、OffScreen Rendering(离屏渲染,基于 GPU)

3、CPU渲染

在介绍以上几种渲染方式之前简单介绍下图像显示的原理:

       通常来说,计算机系统中 CPU、GPU、显示器是以上面这种方式协同工作的。CPU 计算好显示内容提交到 GPU,GPU 渲染完成后将渲染结果放入帧缓冲区,随后视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示。

整个过程就是:CPU准备显示内容(bitmap)------GPU 进行渲染------帧缓冲区(FrameBuffer)存放渲染结果------视频控制器读取------显示器显示

前面介绍的第一种渲染方式:OnScreen Rendering 其实就是上边这个过程,GPU 直接将渲染结果放入帧缓冲区(FrameBuffer)。

第二种渲染方式:OffScreen Rendering 则多了一个步骤,GPU 会先创建一个屏外缓冲区(OffScreenBuffer),然后在其中进行渲染,最后将渲染结果提交到帧缓冲区内(FrameBuffer);这其中还涉及到了两次上下文的转换,首先把当前上下文转换到屏外缓冲区(OffScreenBuffer),然后又转换到帧缓冲区(FrameBuffer)。整个过程会造成很大的消耗,所以应尽量避免离屏渲染。检测离屏渲染的方式:运行程序---点击 模拟器 上方的Debug选项---选择 Color OffScreen-Rendered,屏幕黄色部分就是了。

第三种渲染方式:CPU 渲染,由CPU处理的一种特殊渲染方式,在App内同步完成,渲染得到的bitmap最后再交由GPU用于显示,由于CPU自身做渲染的性能也不好,所以这种方式也是需要尽量避免的。

第一种渲染方式还好理解,那么什么情况下会触发离屏渲染和CPU渲染呢,先给大家看张图:

图片来源

离屏渲染一般由 Core Animation 主动或被动的触发,具体有以下情况:

shouldRasterize(光栅化)

masks(遮罩)

shadows(阴影)

edge antialiasing(抗锯齿)

group opacity(不透明)

CPU 渲染则会被 Core Graphics 的一切操作所触发,以及重写View里的drawRect方法。(所以一切上下文(context)的操作也会触发?希望有大神能解惑。) 

既然知道了离屏渲染和CPU渲染会产生性能问题,那么我们就可通过减少触发这两种渲染方式来进行简单的界面优化。

优化这块iOS 保持界面流畅的技巧这篇文章介绍的很清楚,以下为个人的一些见解。

1、视图颜色尽量设为不透明,这里之前以为是View的背景颜色,但事实是View.layer的isOpaque属性,默认是 No,改为 true 可提高性能。

2、减少 subview 的数量,避免图层的重叠,绘制图形建议使用 CAShapeLayer ,绘制文字可以用底层的 CoreText,嫌麻烦可以用CATextLayer。可参考我的另一篇文章:iOS开发:在视图上绘制文字的3种高效方法以及如何自适应文本高度

3、尽量用CAShapeLayer替代drawRect方法, 原因:内存恶鬼drawRect ,CAShapeLayer 不论是做动画还是图形绘制都非常好用,我另外几篇关于动画的都是用的 CAShapeLayer。

4、关于圆角引起的性能问题,我的做法是利用 CAShapeLayer 画出圆角矩形然后添加到Button的layer上。代码如下:

let btn = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 100))

btn.setTitle("title", for: .normal)

btn.backgroundColor = UIColor.white

view.addSubview(btn)

let shape = CAShapeLayer()

shape.path = UIBezierPath(roundedRect: CGRect(x:0,y:0,width:100,height:100), cornerRadius: 5).cgPath

shape.fillColor = UIColor.brown.cgColor

btn.layer.addSublayer(shape)

下边的是常规的做法

5、UIImageView的size与图片大小保持一致,很多时候我们给控件添加的图片都是被缩放过后的,如果大小不一致也会引起性能问题,特别是滑动tableView的时候,会影响流畅度。检测方法:和检测离屏渲的按钮在同一个地方,名字叫Color Misaligned Images,解决办法,给 UIImage 扩展一个方法重新创建一张规定大小的位图,代码:

extension UIImage{

func scaleImageToSize(_ size:CGSize) -> UIImage{

UIGraphicsBeginImageContextWithOptions(size,false,UIScreen.main.scale)

draw(in: CGRect(x: 0,y: 0, width: size.width, height: size.height))

let reSizeImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!

UIGraphicsEndImageContext()

return reSizeImage

}

}

let img = UIImageView(frame: CGRect(x: 100, y: 100, width: 80, height: 100))

img.image = UIImage(named: "IMG")?.scaleImageToSize(CGSize(width: 80, height: 100))

view.addSubview(img)

上面的那张是常规的添加方法,在多图的时候应尽量避免黄色的出现

6、另开线程下载图片,处理图形绘制,然后再回到主线程进行显示

暂且只想到这些

参考:

绘制像素到屏幕上

iOS 保持界面流畅的技巧

iOS开发之图形渲染分析、离屏渲染、当前屏幕渲染、On-Screen Rendering、Off-Screen Rendering

上一篇 下一篇

猜你喜欢

热点阅读