首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么从后台线程更新UI需要这么长时间?

为什么从后台线程更新UI需要这么长时间?
EN

Stack Overflow用户
提问于 2017-07-05 16:40:34
回答 1查看 1.4K关注 0票数 3

我知道所有UI更新都必须从主线程执行。

但纯粹是为了更深入地了解GCD和分派主要工作的方式:

我有一个运行网络呼叫的按钮,在它的completionHandler中,我最终做到了:

代码语言:javascript
运行
复制
self.layer.borderColor = UIColor(red: 255/255.0, green: 59/255.0, blue: 48/255.0, alpha: 1.0).cgColor
self.layer.borderWidth = 3.0

要改变颜色,需要6-7秒。显然,如果从主线程运行上述代码,它将立即更改边框颜色。

Question1,即使我没有任何其他代码可以运行,为什么UI更改不立即从后台线程发生呢?还在等什么?

有趣的是,如果我单击按钮进行网络调用,然后在textField本身上点击(在6-7秒之前),边框颜色将立即改变。

这是因为:

在后台线程中,我更新了模型,即更改textField颜色,因为我们在后台队列中将UI /视图排队为updated...but,更新UI可能需要几秒钟的时间

但是我马上就点击了textField,并强制对textField及其所有属性(包括边框)进行了超级快速的读取--从主线程(实际用户的触摸总是通过主线程处理)...which,尽管屏幕上还没有红色,但是由于模型上是红色的,它将从它读取并立即改变颜色为红色。

Question2:那个观察是对的吗?

如果我不点击和只是等待:

如果我点击:

我的完整代码如下:

代码语言:javascript
运行
复制
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    @IBAction func isValid(_ sender: Any) {

        let userEmail = textField.text

        let requestURL = NSURL(string: "https://jsonplaceholder.typicode.com")

        var request = URLRequest(url: requestURL as! URL)

        request.httpMethod = "POST"

        let postString = "Anything"

        request.httpBody = postString.data(using: .utf8)

        let task = URLSession.shared.dataTask(with: request) { data, response, error in

            guard let data = data, error == nil else {
                print("error=\(error)")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
            }

            do {

                let json = try? JSONSerialization.jsonObject(with: data, options: [])

                if let _ = json as? [String: Any] {

                    self.textField.layer.borderColor = UIColor(red: 255/255.0, green: 59/255.0, blue: 48/255.0, alpha: 1.0).cgColor
                    self.textField.layer.borderWidth = 3.0

                }

            } catch let error as NSError {
                print(error)
            }

        }
        task.resume()

    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-05 17:01:37

如果您试图从后台线程执行UI更新,“结果是未定义的”。我所见过的最常见的效果是您所描述的--在更新出现之前很长时间的延迟。我见过的第二个最常见的效果是撞车。第三种最常见的效果是某种绘画艺术品。

从后台线程执行UI更新的结果确实是不确定的。您有多个处理器核同时访问相同的硬件资源,并且这些访问之间的确切时间是不可知的和无限可变的。这就像一台没有显示器的电脑,只有两个键盘和两个鼠标,以及两个操作员同时编辑同一个文档。每个人使用键盘的操作都会改变文档的状态,并破坏其他人试图应用的更改。光标将出现在错误的位置。文件中的文本数量将与预期不同。滚动位置将关闭。等等

同样,如果每个内核都试图访问硬件资源来进行屏幕刷新,那么这些访问将相互交叉和冲突。

正如Martin在他的评论中所说的,UIKit代码是专有的,因此我们无法知道的细节--出了什么问题。我们只知道糟糕的事情会发生,所以不做

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44931759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档