iOS开发

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)
    }
}
结果分析:

从图中点击按钮后,虽然任务是在同一个子线程执行,但是没有按顺序执行

结论:
在子线程中是不能进行UI更新的,而可以更新的结果只是一个幻像:因为子线程代码执行完毕了,
又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI。
如果子线程一直在运行,则子线程中的UI更新的函数栈主线程无法获知,即无法更新
上一篇下一篇

猜你喜欢

热点阅读