主页 阿里、字节:一套高效的iOS面试题之视图&图形
Post
Cancel

阿里、字节:一套高效的iOS面试题之视图&图形

前言

本文具有强烈的个人感情色彩,如有观看不适,请尽快关闭. 本文仅作为个人学习记录使用,也欢迎在许可协议范围内转载或分享,请尊重版权并且保留原文链接,谢谢您的理解合作. 如果您觉得本站对您能有帮助,您可以使用RSS方式订阅本站,感谢支持!

本篇我们来讲一下 阿里、字节:一套高效的iOS面试题 中的视图&图形相关的问题.

视图&图像相关

主要问题列表如下:

  1. AutoLayout的原理,性能如何
  2. UIView & CALayer的区别
  3. 事件响应链
  4. drawrect & layoutsubviews调用时机
  5. UI的刷新原理
  6. 隐式动画 & 显示动画区别
  7. 什么是离屏渲染
  8. imageName&imageWithContentsOfFile区别
  9. 多个相同的图片,会重复加载吗
  10. 图片是什么时候解码的,如何优化
  11. 图片渲染怎么优化
  12. 如果GPU的刷新率超过了iOS屏幕60Hz刷新率是什么现象,怎么解决

1.AutoLayout的原理,性能如何?

AutoLayout的原理

来历 一般大家都会认为Auto Layout这个东西是苹果自己搞出来的,其实不然,早在1997年Alan Borning, Kim Marriott, Peter Stuckey等人就发布了《Solving Linear Arithmetic Constraints for User Interface Applications》论文(论文地址:http://constraints.cs.washington.edu/solvers/uist97.html)提出了在解决布局问题的Cassowary constraint-solving算法实现,并且将代码发布在他们搭建的Cassowary网站上http://constraints.cs.washington.edu/cassowary/。后来更多开发者用各种语言来写Cassowary,比如说pybee用python写的https://github.com/pybee/cassowary。自从它发布以来JavaScript,.NET,JAVA,Smalltall和C++都有相应的库。2011年苹果将这个算法运用到了自家的布局引擎中,美其名曰Auto Layout。

论文下载链接比较慢,我下载了一份Cassowary原文放到了我的博客 大家可以自由下载.

AutoLayout的原理就是用Cassowary算法来将布局问题抽象成线性不等式,并分解成多个位置间的约束
因为多了计算视图大小frame的过程,所以性能肯定没有指定Frame坐标要快.

详细的原理以及高阶原理请参考戴铭老师的文章 戴铭老师写的 深入剖析Auto Layout,分析iOS各版本新增特性

性能如何?

下面是WWDC2018 High Performance Auto Layout中对比的iOS12和iOS11下分别使用自动布局的性能对比现场.

经过实验得出如下图标结论:

iOS12之前,视图嵌套的数量对性能的影响是呈指数级增长的,而iOS12优化之后对性能的影响是线性增长,对性能消耗不大。

无论如何优化也肯定不如CGRectFrame那样的设置更加直接,性能更好.

2.UIView & CALayer的区别

区别UIViewCALayer
继承父类UIView:UIResponder:NSObjectCALayer:NSObject
用途可以处理触摸事件不处理用户的交互,不参与响应事件传递
两者关系有一个CALayer成员变量 eg: view.layer是UIView的成员变量
分工处理交互层事件并包装各种图形的简单设置底层渲染图形,支持动画

3.事件响应链

下面这篇文章我已经在前几篇将runloop的时候提了不止一次,前列建议阅读,快手的同事大部分都以这个理解为标准

iOS触摸事件全家桶

4. drawrect & layoutsubviews调用时机

layoutSubviews:(相当于layoutSubviews()函数)在以下情况下会被调用:

  1. init初始化不会触发layoutSubviews。
  2. addSubview会触发layoutSubviews。
  3. 设置view的Frame会触发layoutSubviews (frame发生变化触发)。
  4. 滚动一个UIScrollView会触发layoutSubviews。
  5. 旋转Screen会触发父UIView上的layoutSubviews事件。
  6. 改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
  7. 直接调用setLayoutSubviews。

drawrect:(drawrect()函数)在以下情况下会被调用:

  1. drawrect:是在UIViewController的loadView:ViewDidLoad:方法之后调用.
  2. 当我们调用[UIFont的 sizeToFit]后,会触发系统自动调用drawRect:
  3. 当设置UIView的contentMode或者Frame后会立即触发触发系统调用drawRect:
  4. 直接调用setNeedsDisplay设置标记 或setNeedsDisplayInRect:的时候会触发drawRect:

知识点扩充: 当我们操作drawRect方法的时候实际是在操作内存中存放视图的backingStore区域,用于后续图形的渲染操作,如果不理解可以看下UIView的渲染过程.

5.UI的刷新原理

这个问题我不知道问的是不是iOS离屏渲染过程,我来简单的回到一下这个吧

iOS 的MainRunloop 是一个60fps 的回调,也就是说16.7ms(毫秒)会绘制一次屏幕在这过程中要完成以下的工作:

  • view的缓冲区创建
  • view内容的绘制(如果重写了 drawRect)
  • 接收和处理系统的触摸事件

我们看到的UI图形实际上是CPU和GPU不断配合工作的结果.经过UIView的渲染过程 后我们的UI会不间断的接收系统图给我们的事件.

由于主线程的runloop 一直在回调,我们的UI就得到了刷新的窗口,是渲染还是处理事件都是因为runloop不断工作的结果.前几篇我们学过 main线程的runloop默认是启动的.因为我们响应交互.

不知道我这样回答是否满足这个问题的答案.如果回答的不对烦请下方评论区留言 告知我将持续改进.

6.隐式动画 & 显示动画区别

隐式动画一直存在 如需关闭需设置
显式动画是不存在,如需显式 要开启

只需要观察动画执行完成的结果 比如: 一个简单UIView的frame移动 如果从A点移动到B点 移动完成 回到原始位置就是隐式动画

Core Animation 是显式动画.因为它既可以直接对其layer属性做动画,也可以覆盖默认的图层行为.

7.imageName&imageWithContentsOfFile区别

区别UIViewimageWithContentsOfFile
不同点会图片缓存到内存中无缓存

8.什么是离屏渲染

iOS离屏渲染的深入研究

9.多个相同的图片,会重复加载吗

不会,GPU有 像素点缓存的mask.

10.图片是什么时候解码的,如何优化

是加载到内存中,从UIImge->CGImage->CGImageSourceCreateWithData(data) 创建ImageSource变成bitmap位图,这些工作都是CoreAnimation在图片被加载到内存中存在在backingStore里,送给GPU流水线处理之前被解码.

如何优化

自己手动操作图片的编码API

CGImageSource开头的哪些,根据合理利用时机和操作系统资源调整出一套缓存小加载快的库.

参考PINRemoteImage或者YYWebImage开源

11.图片渲染怎么优化

可以从阴影,圆角入手.帧率,电量,图片的锯齿等等.

iOS开发-视图渲染与性能优化

12.如果GPU的刷新率超过了iOS屏幕60Hz刷新率是什么现象,怎么解决

现象是 图形清晰,场景逼真,但是一般arm芯片的GPU 刷新超过60Hz一定会超级费电,手机发热导致降频.FPS降低,因为低能耗电量不足,无法支持GPU高刷新率

解决办法只能用xcode自带工具检测,看渲染过程哪里可以优化.

总结

简单回答了一些图形相关的问题,大部分都是iOS离屏渲染,这个地方大家要认真学习.很多资料看起来比较耗时.

该博客文章由作者通过 CC BY 4.0 进行授权。

阿里、字节:一套高效的iOS面试题之多线程

阿里、字节:一套高效的iOS面试题之性能优化