我已经实现了对服务器的url请求,并使用收到的JSON。但是有一件奇怪的事情我无法解释。
我的视图控制器类:
import UIKit
class TopRatedViewController: UIViewController {
var importedRates: NSArray = []
var successfullyConnected: Bool = true
@IBAction func buttonTapped(sender: AnyObject) {
print(importedRates)
}
override func viewDidLoad() {
super.viewDidLoad()
//MARK: Connection to web service
let urlString: String = "http://alma.com/get.php"
let url = NSURL(string: urlString)
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfig)
let task = session.dataTaskWithURL(url!, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
if error != nil {
self.successfullyConnected = false
}else {
var jsonresult = NSArray()
do {
jsonresult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
self.importedRates = jsonresult
} catch _ {
print("error loading rates")
}
}
})
task.resume()
print(importedRates)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
因此,如果我运行我的应用程序打印(导入速率)命令会打印空数组。在调试窗口中,我看到其中没有任何内容。
但是,如果我单击按钮,然后应该打印此变量 - 它成功打印了一个包含 40 个元素的数组。谁能解释为什么它会这样工作?
我期望这个变量应该在viewdidload方法中填充数据。
您正在启动viewDidLoad
的异步调用,该调用在完成时设置self.importedRates = jsonresult
。
completionHandler
中的所有内容在print(importedRates)
后以非常高的概率执行,更准确地说:此时,网络请求返回(取决于您的网络和请求,几微秒到几分钟)
这就是按下按钮起作用的原因:当您按下按钮时,请求确实已完成并正确填充了数组。
强烈建议不要在主线程上使用同步请求。这可能会导致应用无响应(因为所有用户输入都在主线程上处理,只要同步调用正在等待响应,就无法继续。
相反,如果您期望的数据到达,请从completionHandler
中调用视图控制器的方法,该方法以您希望使用的方式使用 now-set 属性。例如,如果您尝试填充self.tableView : UITableView!
:
let task = session.dataTaskWithURL(url!, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
if error != nil {
self.successfullyConnected = false
}else {
var jsonresult = NSArray()
do {
jsonresult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
dispatch_async(dispatch_get_main_queue()) {
self.importedRates = jsonresult
self.tableView.reloadData() // look here
}
} catch _ {
print("error loading rates")
}
}
})
task.resume()