我对此的第一遍是JavaScript代码示例,它看起来应该可以工作,但仔细检查就会发现行为不同。我的Swift代码目前带有SwiftyJSON:

    for(var index = 0; index < datesToLoad.count; index += 1) {
        var formattedDate = formatter.stringFromDate(datesToLoad[index]);
        if (presentLocation["days"][formattedDate] == nil) {
            loadDataFromURL(NSURL:"http://api.sunrise-sunset.org/json?formatted=0&lat=\(presentLocation.coordinate.latitude)&lon=\(presentLocation.coordinate.longitude)&date=\(formattedDate)&formatted=0", completion: {(data, error) -> Void in {
                if (var json = JSON(data:data)) {
                    presentLocation["days"][formattedDate]["sunrise"] = parser(json["results"]["sunrise"]);
                    presentLocation["days"][formattedDate]["sunset"] = parser(json["results"]["sunset"]);
                }
            }
        }
    }

现在,我希望代码不会按预期运行。我要完成的工作是,对于列表的每个formattedDate值,都会进行一个异步调用以从URL检索数据,并且每个API调用都将与进行formattedDate调用时仍处于 Activity 状态的loadDataFromURL()值一起使用。我预期将发生的是,循环将快速运行,并生成一些异步请求,并且formattedDate将使用定义的最后一个值。我可能可以解决不知道如何在Swift中正确执行此操作的问题,因为从API返回的数据会给出多个时间戳,但是我想知道通过回调函数查看formattedDate的多个值的首选方式,在调用其loadDataFromURL()函数时处于 Activity 状态。

我还可以通过完全展开(四个元素)循环并为每个基于闭包的API调用使用单独的变量名称来获得所需的结果,但是我真的更想知道处理这种问题的正确方法是什么。

最佳答案

每次通过for循环都会创建一个新的formattedDate变量,该变量与在其他任何遍次上创建的formattedDate变量无关。

因此,您的循环应该可以实现您的预​​期。

游乐场演示:

import XCPlayground
import UIKit

var blocks: [()->Void] = []

for i in 0..<5 {
    var s = "\(i)"
    blocks.append( { print(s) } )
}

print("calling blocks")

for block in blocks {
    block()
}

输出:
calling blocks
0
1
2
3
4

07-26 09:43