swift - 变量在闭包之外不会改变

标签 swift

var arrayLength:Int = 0 // is equal to 0

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let urlPath = "http://example.com/json"

    let url = NSURL(string: urlPath)!
    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithURL(url, completionHandler: {
        data, response, error in

        if (error? != nil) {
            println(error)
        } else {
            var jsonResponse: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil)

            let json = JSON(jsonResponse!)
            self.arrayLength = json["dump"].array?.count as Int!
            println("Second: \(self.arrayLength)") // is equal to 3

            for postIndex in 0...self.arrayLength-1 {
                println(json["dump"][postIndex]["title"])
            }
        }

    })
    task.resume()

    println(arrayLength) // is equal to 0 again

我设置了

var arrayLength:Int = 0

在代码的开头。稍后在 viewDidLoad() 内部我将其更改为 3。当我调用它时,在任务 block 外部它再次等于 0。这里的问题是什么以及我做错了什么?

最佳答案

是的,您正在更改闭包中的 arrayLengthvar。您在这里遇到的问题只是线程工作的正常方式。

  1. viewDidLoad 启动时,您在主线程上
  2. let task = session.dataTaskWithURL(url, completionHandler: { ... 定义了一个新任务,它还没有执行
  3. task.resume() 在另一个线程上启动此任务。这需要一些时间才能完成。完成后,您的 arrayLength 将被更改
  4. 您立即在主线程上询问您的 arrayLength

这里:

     println(arrayLength) // is equal to 0 again

不是 arrayLength 再次等于 0,您没有给任务足够的时间来执行和更改该值。

编辑:如果您需要在闭包完成后检查 arrayLength...

只需创建一个函数并在闭包中最后调用它即可。像这样:

override func viewDidLoad() {
   ...

    let task = session.dataTaskWithURL(url, completionHandler: {
        data, response, error in

        if (error? != nil) {
            println(error)
        } else {
            var jsonResponse: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil)

            let json = JSON(jsonResponse!)
            self.arrayLength = json["dump"].array?.count as Int!
            println("Second: \(self.arrayLength)") // is equal to 3

            for postIndex in 0...self.arrayLength-1 {
                println(json["dump"][postIndex]["title"])
            }

            functionToDoSomethingAtTheEndOfTheClosure();
        }

    })
    task.resume()
}

func functionToDoSomethingAtTheEndOfTheClosure() {
  // this is going to be executed at the end of the closure's code
}

关于swift - 变量在闭包之外不会改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29484783/

相关文章:

json - 使用字典将 alamofire 中的 JSON 数据解析为数组

sqlite - 如何调用sqlite3_open(通过引用传递不透明指针)

ios - 为什么在 swift 5 中更改 Root View 时看不到启动(启动)屏幕?

ios - InputAccessoryView 未显示 - Swift 3 Xcode 8.3 beta( Non-Storyboard )

swift - PrepareForSegue 不适用于跳转到不同 View Controller 的函数

ios - 如何更改 Swift 4 中基于发送者的操作函数中使用的属性

ios - 为什么我的代码在线程 6 : NSOperationQueue? 中运行时崩溃

ios - 在自定义 UINavigationController 类中创建 UINavigationBar 时出错

Swift:无法识别泛型的类型协议(protocol)

ios - iOS-选择模型类别