系统: Mac OS 10.14.6, XCode 11,swift 4.2
写作时间:2019-10-12
说明
写iOS的同学都知道,如果更新update UI不在主线程,直接crash。那到底为什么,update UI必须要在主线程呢?原因有如下3点:
1. 在Cocoa Touch, UIApplication建立在主线程,这个单例是App启动的第一部分。
所有在屏幕上面的Views,Label,Button都是建立在UIApplication的实体上。所以当你点击Button,你必须在主线程上处理。同样的,相关操作在UI的事件,比如放大、缩小,动画等都必须要在主线程上处理。
2. 图形的处理流程graphics pipeline,绝对是同步处理的.
举个例子,在UILabel显示用户名. 你异步请求用户的名字,当结果返回时,显示用户名.
UIKit, 需要把字体打印到屏幕上,因为字体本身是向量,需要把字体转换为像素,可能要裁剪字体大小,可能要处理透明度,图形渲染器需要计算哪些像素要显示. 这些像素需要把这些图层放在一起,一秒内处理60次,这样子才不会掉帧.
把像素画到Phone屏幕上,在LED上照亮像素点,这些操作需要一并处理. 这里要是异步处理,就会导致不知道那些哪里已经渲染完,哪里没有. 如果你非要异步处理,会出现屏幕闪烁,有的部分显示不出来的问题。
3. 最后,在主线程上更新UI,是最简单的,省了做各种决定如何显示,避免出现bugs。最佳实践为,异步组装数据提高体验,在主线程同步处理UI。
It’s a conscious design decision from Apple’s side to not have UIKit be thread-safe. Making it thread-safe wouldn’t buy you much in terms of performance; it would in fact make many things slower. And the fact that UIKit is tied to the main thread makes it very easy to write concurrent programs and use UIKit. All you have to do is make sure that calls into UIKit are always made on the main thread.
Thread-Safe Class Design
- View磨皮filters过滤器效果,圆角View, 或者用到CIFilter. 这些操作比较集中,需要cache缓存, 这些操作需要异步处理好,最后得到像素数据再调用主线程渲染到屏幕上.
- 创建一个复杂动画图片。需要先处理动画数据,最后再生成动画的图片,渲染到屏幕上.
- 下载网络资源,比如用户数据,先异步后台下载数据,下载完毕后再调用主线程渲染到屏幕上.
参考
https://www.quora.com/Why-must-the-UI-always-be-updated-on-Main-Thread
https://developer.apple.com/videos/play/wwdc2012/211/
https://juejin.im/post/5c406d97e51d4552475fe178
https://www.objc.io/issues/2-concurrency/thread-safe-class-design/
探讨了在iOS开发中,为何必须在主线程更新UI的原因。主要从三个方面解析:UIApplication建立于主线程,图形处理流程同步进行,及简化并发编程避免bug。深入理解有助于提升iOS应用性能。
1353

被折叠的 条评论
为什么被折叠?



