我是学习iOS和Swift的新手,所以这里可能有一些非常基本的东西我不明白。我正在使用agent库在Swift中发送HTTP请求。现在,我正忙着创建请求并解析JSON响应。
我有一个非常简单的用户界面,其中包含一个按钮和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"]!
})
}
我不理解的部分是self.updateMe.text = json["safe_title"]!
语句,它只是更新名为UILabel
的{{1}}上的某些文字。这需要几乎整整30秒才能在UI中反映出来。
我知道HTTP请求本身非常快 - 如果我卷曲该URL,它会立即恢复。似乎updateMe
对象正在建立连接并且响应速度非常快。
我错过了一些非常基本的东西吗?我应该以不同的方式更新UI吗?所有指针都很受欢迎!
更新
通过另一个SO帖子,我理解Agent
内部的块是后台线程,我需要在主线程上进行UI更新。我更新了我的功能,看起来像这样,我得到了理想的结果。但是,现在我想知道这样做是否有些不正确的事情?
req.end
答案 0 :(得分:5)
正在发生的事情是您的HTTP请求正在后台线程上运行。当它调用你提供的回调时,你仍然在那个后台线程上。在iOS 所有UI工作必须在主线程上完成。最简单的方法是使用GCD的dispatch_async
,如下所示:
dispatch_async(dispatch_get_main_queue()) {
[weak self] in
self?.updateMe.text = json["safe_title"]!
return
}
所以你的整个功能看起来像是:
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
}
})
}
关于[weak self] in
的位是这样的,因此您不会创建strong reference cycle。最后的return
是因为你有一个只有一个表达式的闭包。在这种情况下,Swift将尝试implicitly return a value based on that statement,在这种情况下,这不是你想要的。