在 iOS开发过程中,大家知道更新UI,需要在主线程中,但是应该都没去细想一下......................
为什么要在主线程中?或者说为什么不能在子线程中更新UI?
GUI为了性能(不知道GUI的可以自己查一下),故意让你只能在一个线程里面操作的,多线程操作一个UI,很容易导致,或者极其容易导致反向加锁和死锁问题。其实不光是GUI,同样的道理在几乎所有编程领域里都是这样的,这背后是线程同步的开销问题。
通俗的讲显然两个线程不能同时draw,否则屏幕会花;不能同时insert map,否则内存会花;不能同时write buffer,否则文件会花。需要互斥,比如锁。结果就是同一时刻只有一个线程可以做UI。那么当两个线程互斥几率较大时,或者保证互斥的代码复杂时,选择其中一个长期持有其他发消息就是典型的解决方案。所以普遍的要求UI只能单线程。
像UIKit这样大的框架上确保线程安全是一个重大的任务,会带来巨大的成本。UIKit不是线程安全的,假如在两个线程中设置了同一张背景图片,很有可能就会由于背景图片被释放两次,使得程序崩溃。或者某一个线程中遍历找寻某个subView,然而在另一个线程中删除了该subView,那么就会造成错乱。apple有对大部分的绘图方法和诸如UIColor等类改写成线程安全可用,可还是建议将UI操作保证在主线程中。
事实上在子线程中如果要对其他UI 进行更新,必须等到该子线程运行结束,而对响应用户点击的Button的UI更新则是及时的,不管他是在主线程还是在子线程中做的更新,意义都不大了,因为子线程中对所有其他ui更新都要等到该子线程生命周期结束才进行。
在子线程中是不能进行UI 更新的,我们看到的UI更新其实是子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI。如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新。只有极少数的UI能直接进行UI更新,因为开辟线程时会获取当前环境,如点击某个按钮,这个按钮响应的方法是开辟一个子线程,在子线程中对该按钮进行UI 更新是能及时的,如上面的换背景图,但这没有任何意义。
网友评论