iOS为什么在主线程刷新UI
2018-12-15 本文已影响284人
7_c5dc
class UpdateUIViewController: PurpleNavigationViewController {
var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
print("主线程:%@", Thread.main)
button = UIButton(type: .custom)
button.setTitle("UI", for: .normal);
button.titleLabel?.numberOfLines = 0
button.setTitleColor(UIColor.orange, for: .normal)
button.backgroundColor = UIColor.lightGray
button.frame = CGRect(x: 0, y: 70, width: UIScreen.main.bounds.size.width, height: 100)
button.addTarget(self, action: #selector(buttonDidClick(_:)), for: .touchUpInside)
view.addSubview(button)
}
@objc func buttonDidClick(_ sender: UIButton) {
//切换到子线程操作UI
Thread.detachNewThreadSelector(#selector(subThreadTest), toTarget: self, with: nil)
}
@objc func subThreadTest() {
//step1
//这里并不会立即更新,而是等休眠4s之后回调主线程再更新
button.setTitle("当前线程:\(Thread.current)", for: .normal)
//如果想立即更新,需要手动切换到主队列
// DispatchQueue.main.async {
// self.button.setTitle("当前线程:\(Thread.current)", for: .normal)
// }
//step2
print("当前线程:%@", Thread.current)
print("主线程:%@,是否是主线程:%d", Thread.main, Thread.isMainThread)
//step3
let button1 = UIButton(type: .custom)
button1.setTitle("主线程:\(Thread.main)", for: .normal)
button1.backgroundColor = UIColor.lightGray
button1.titleLabel?.numberOfLines = 0
button1.setTitleColor(UIColor.orange, for: .normal)
button1.frame = CGRect(x: 0, y: 200, width: UIScreen.main.bounds.size.width, height: 100)
view.addSubview(button1)
Thread.sleep(forTimeInterval: 4)
}
}
结果分析:
从图中点击按钮后,虽然任务是在同一个子线程执行,但是没有按顺序执行
- step1:更新title没有立即执行
- step2:打印先于step1执行
- step3:也没有立即执行
- 如果想立即更新UI,需要手动切换到主队列,否则要等子线程结束返回到主线程才能刷新UI
结论:
在子线程中是不能进行UI更新的,而可以更新的结果只是一个幻像:因为子线程代码执行完毕了,
又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI。
如果子线程一直在运行,则子线程中的UI更新的函数栈主线程无法获知,即无法更新