Swift:在for循环中调用完成处理程序方法

时间:2016-09-23 07:26:20

标签: ios swift

我想了解for循环中包含完成处理程序方法的行为。

请参阅以下示例,其中我尝试获取2个地址的纬度/经度坐标。

PHAssetResourceRequestOptions

输出就像这样

let addressArray = ["1 Infinite Loop, Cupertino", "809, Harvard Ave, Sunnyvale, CA - 94087"]
var coordinatesArray = [CLLocationCoordinate2D]()

for i in 0 ..< addressArray.count {
    print(i)
    let address = addressArray[i]
    geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in
        print("Address = \(address)");
        if let placemark = placemarks?.first {
            let coordinate = placemark.location?.coordinate
            self.coordinatesArray.append(coordinate!)
        }
    })
}

// Do something here after that that

我想知道为什么代码中没有打印其他地址。第二个for循环没有调用geocodeAddressString方法。假设在for循环结束后应用程序执行没有结束,我做了很多其他事情。

1 个答案:

答案 0 :(得分:1)

说明:

  • 有循环运行N次(addressArray.count)。
  • 在每次迭代期间,进行地理编码请求。
  • 获取地点标记需要一些时间。
  • 这是一种异步方法,因此它不会阻止执行(意味着循环继续运行,并且不会等到地理请求完成)。
  • 当完成特定迭代的地理编码请求时,将执行它的完成处理程序。

问题:

  • 由于无法保证完成顺序,因此最好使用字典而不是数组。
  • 不要使用数组,因为完成顺序可能不是连续的。
  • 例如,第一个请求可能在第二个请求完成后完成。

解决方案:

  • 对于给定的整数索引,coordinates[index]将对应addressArray[index]

代码(提议修复):

class Test {

    let geocoder = CLGeocoder()

    //Better use a dictionary instead of an array
    var coordinates = [Int: CLLocationCoordinate2D]()

    func f1() {

        for i in 0 ..< addressArray.count {
            print(i)
            let address = addressArray[i]

            geocoder.geocodeAddressString(address) {placemarks, error in
                print("Address = \(address)");
                if let placemark = placemarks?.first {
                    let coordinate = placemark.location?.coordinate

                    self.coordinates[i] = coordinate
                }
            }
        }
    }
}