iOS请求后需要很长时间才能更新视图?

bit*_*ops 1 http ios swift

我是学习iOS和Swift的新手,所以这里可能有一些非常基本的东西,我不明白.我正在使用代理库在Swift中发送HTTP请求.现在,我正忙着创建请求并解析JSON响应.

我有一个非常简单的UI,带有一个按钮UILabel,我想用一些JSON的结果更新.

这是我的代码:

func updateWithJson() -> Void {
    let req = Agent.get("http://xkcd.com/info.0.json")
    req.end({ (response: NSHTTPURLResponse!, data: Agent.Data!, error: NSError!) -> Void in
        let json = data! as Dictionary<NSString, NSString>
        // this takes almost 30 seconds to propagate to the UI...
        self.updateMe.text = json["safe_title"]!
    })
}
Run Code Online (Sandbox Code Playgroud)

我不理解的部分self.updateMe.text = json["safe_title"]!是刚刚更新UILabel被调用文本的语句updateMe.这需要几乎整整30秒才能在UI中反映出来.

我知道HTTP请求本身非常快 - 如果我卷曲该URL它会立即回来.它似乎也是Agent对象正在建立连接并快速返回响应.

我错过了非常基本的东西吗?我应该以不同的方式更新UI吗?所有指针都很赞赏!

更新 通过另一个SO帖子,我的理解是内部的块req.end是后台线程,我需要在主线程上进行UI更新.我更新了我的功能,看起来像这样,我得到了理想的结果.但是,现在我想知道这样做有什么不对吗?

    func updateWithJson() -> Void {
        let req = Agent.get("http://xkcd.com/info.0.json")
        req.end({ (response: NSHTTPURLResponse!, data: Agent.Data!, error: NSError!) -> Void in
            let json = data! as Dictionary<NSString, NSString>
            var text = json["safe_title"]!
            dispatch_sync(dispatch_get_main_queue()) {
                self.updateMe.text = text
            }
        })
    }
Run Code Online (Sandbox Code Playgroud)

Mik*_*e S 6

发生的事情是您的HTTP请求正在后台线程上运行.当它调用你提供的回调时,你仍然在那个后台线程上.在iOS中,所有UI工作必须在主线程上完成.最简单的方法是使用GCD,dispatch_async如下所示:

dispatch_async(dispatch_get_main_queue()) {
    [weak self] in
    self?.updateMe.text = json["safe_title"]!
    return
}
Run Code Online (Sandbox Code Playgroud)

所以你的整个功能看起来像:

func updateWithJson() -> Void {
    let req = Agent.get("http://xkcd.com/info.0.json")
    req.end({ (response: NSHTTPURLResponse!, data: Agent.Data!, error: NSError!) -> Void in
        let json = data! as Dictionary<NSString, NSString>
        dispatch_async(dispatch_get_main_queue()) {
            [weak self] in
            self?.updateMe.text = json["safe_title"]!
            return
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

关于这一点[weak self] in,你不会创建一个强大的参考周期.将return在年底有没有因为你必须在它只有一个表达式封闭.在这种情况下,Swift将尝试隐式返回基于该语句的值,在这种情况下,这不是您想要的.