循环中的 NSURLSession

NSURLSession in a loop

我希望 运行 这段代码可以从 URL 中获取多张图片,但是尽管循环 运行 遍历了数组中的每个对象,但唯一保存的对象是最后一个。有更好的方法吗?

编辑: 似乎所有图像都是从不同的 URL 保存的,但它们都以相同的文件名保存,循环中的最终文件名。这似乎是由于在 NSURLSession 和将图像写入文件时发生延迟引起的,文件名已经设置为循环的最后一个。

for object in objectArray {

     url = NSURL(string:object.urlToLoad)
     imageFile = paths.stringByAppendingPathComponent("\(object.filename).png")

     let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
          data.writeToFile(imageFile, atomically: true)
          return
     }

     task.resume()
}

感谢您的帮助!

问题是它们都是 capturing/sharing 相同的 imageFile 变量,因为它是在 for 的范围之外声明的。所以首先你要遍历 n 次循环,在你进行时用下一个文件名覆盖 imageFile 变量并触发异步下载。然后,稍后,当每个 n 闭包在下载完成时实际执行时,它们都引用相同的文件名,该文件名与数组中的最后一个值匹配。

尝试在它前面加上一个 let,从而在每次迭代中声明一个新的局部变量,每个闭包依次捕获该局部变量。你也应该对 url 做同样的事情,即使它碰巧不是问题。

一般来说,这是另一个很好的例子,说明您应该如何在每一次机会中使用 let 而不是 var,并避免在外部范围内重复使用变量的做法,除非您特别指定想要将数据传送到外部范围。

这里有一些独立的代码演示了这一点,没有 URL 下载方面,只有 5 个并行的睡眠和打印 运行:

import Dispatch
let q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

var shared: String = "shared=x"
for x: UInt32 in 1...5 {

    shared = "shared=\(x)"
    let unique = "unique=\(x)"
    dispatch_async(q) {
        sleep(x)
        println("\(shared), \(unique)")
    }

}

println("for loop completed, \(shared)")
dispatch_main()