Swift:for循环中的异步调用

时间:2016-09-22 08:21:00

标签: ios swift

我试图在swift中执行以下操作 - 尝试反转解码数组中的地址列表并打印其纬度/经度坐标。我的代码如下。

    let addressArray = ["Address 1", "Address 2"]
    var coordinatesArray = [CLLocationCoordinate2D]()

    override func viewDidLoad() {
        super.viewDidLoad()
        createAddressList()
        printAddressList()
    }

    func printAddressList() {
        for i in 0 ..< addressArray.count  {
            print("Address = \(addressArray[i]) Coordinates = \(coordinatesArray[i].latitude),\(coordinatesArray[i].latitude)")
    }

    func createAddressList() {
        for i in 0 ..< addressArray.count {
            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!)
                }
            })
        }
    }
}

代码只打印解码的第一个地址,然后没有任何反应。

我确实对此进行了修复,如下所示,即从viewDidLoad方法移动printAddressList调用

func createAddressList() {
    if count < self.addressArray.count {
        let address = addressArray[count]
        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!)
            }
            print("Count = \(self.count)")
            self.count += 1
            self.createAddressList()
        })
    } else {
        printAddressList()
    }
}

即使后一种解决方案有效,但我发现它不干净,想知道正确的方法,使代码可读和清洁。

2 个答案:

答案 0 :(得分:5)

使用这种结构怎么样?

let workGroup = dispatch_group_create()

for i in 0..<addressArray.count {

    dispatch_group_enter(workGroup)

    performGeoCoding({  successCallback : 

            dispatch_group_leave(workGroup)

    })
}

dispatch_group_notify(workGroup, dispatch_get_main_queue()){ 
    successCallback()   
    printAddressList()                    
}

有关于dispatch_group here的非常好的教程。

答案 1 :(得分:0)

更多更新将是这样的:

let dispatchGroup = DispatchGroup()

for address in addressArray {
    dispatchGroup.enter()

    performGeoCoding { address in 
        dispatchGroup.leave()
    }
}

dispatchGroup.notify(queue: .main) {
    completionHandler()   
}