我是学习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)
发生的事情是您的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将尝试隐式返回基于该语句的值,在这种情况下,这不是您想要的.
| 归档时间: |
|
| 查看次数: |
1114 次 |
| 最近记录: |