为什么调试器显示变量为空

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()