为什么调试器显示变量为空
Why debugger shows that variable is empty
我已经对服务器实施了 url 请求,并打算处理收到的 JSON。
但是有一件奇怪的事情我无法解释。
我的ViewControllerclass:
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.
}
}
所以如果我 运行 我的应用程序 print(importedRates) 命令打印空数组。在调试 window 中,我看到里面什么也没有。
但是。如果我点击按钮然后应该打印这个变量 - 它成功地打印了一个包含 40 个元素的数组。
谁能解释为什么它会这样工作?
我期望这个变量应该在 viewdidload 方法中填充数据。
您正在 viewDidLoad
中开始一个异步调用,它在完成时设置 self.importedRates = jsonresult
。
completionHandler
里面的所有东西都是在print(importedRates)
之后以非常高的概率执行的,更准确的说:那个时候,网络请求回来了(取决于你的网络和请求,几微秒到几分钟)
这就是按下按钮起作用的原因:当您按下按钮时,请求确实完成并正确填充了数组。
强烈建议不要在主线程上使用同步请求。这可能会导致您的应用程序无响应(因为所有用户输入都在主线程上处理,并且只要同步调用正在等待响应就无法继续。
相反,如果您期望的数据到达,请从 completionHandler
中调用视图控制器的方法,该方法以您希望的方式使用现在设置的 属性。例如,如果您尝试填充 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()
我已经对服务器实施了 url 请求,并打算处理收到的 JSON。 但是有一件奇怪的事情我无法解释。
我的ViewControllerclass:
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.
}
}
所以如果我 运行 我的应用程序 print(importedRates) 命令打印空数组。在调试 window 中,我看到里面什么也没有。
但是。如果我点击按钮然后应该打印这个变量 - 它成功地打印了一个包含 40 个元素的数组。 谁能解释为什么它会这样工作?
我期望这个变量应该在 viewdidload 方法中填充数据。
您正在 viewDidLoad
中开始一个异步调用,它在完成时设置 self.importedRates = jsonresult
。
completionHandler
里面的所有东西都是在print(importedRates)
之后以非常高的概率执行的,更准确的说:那个时候,网络请求回来了(取决于你的网络和请求,几微秒到几分钟)
这就是按下按钮起作用的原因:当您按下按钮时,请求确实完成并正确填充了数组。
强烈建议不要在主线程上使用同步请求。这可能会导致您的应用程序无响应(因为所有用户输入都在主线程上处理,并且只要同步调用正在等待响应就无法继续。
相反,如果您期望的数据到达,请从 completionHandler
中调用视图控制器的方法,该方法以您希望的方式使用现在设置的 属性。例如,如果您尝试填充 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()