2017-11-06 17 views
0

私は、複数の場所に対して同時に逆ジオコーディングを実行しようとしています。そこで私は関数performReverseGeoLocationを作成します。問題は、CLGeocoder().reverseGeocodeLocation閉鎖以来、completionHandlerLocationsが最初に実行されることです。 forループ内のCLGeocoder().reverseGeocodeLocationがすべて完了した後に、呼び出し元が補完ハンドラを取得するように、これらの関数をどのように変更しますか?私が試してみましたswift - タスクの完了方法

コード:

private func getImageLocation() { 
    performReverseGeoLocation(completionHandlerLocations: { (cities, countries) in 
     print("***** This is executed before the reverse geo code location is done") 
    }) 
} 

private func performReverseGeoLocation(completionHandlerLocations: @escaping (_ cities: [String], _ countries: [String]) -> Void) { 

    var cities = [String]() 
    var countries = [String]() 

    for image in self.images { 
     let longitude = image.longitude 
     let latitude = image.latitude 

     let location = CLLocation(latitude: latitude, longitude: longitude) 

     CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in 
      print("***** This is executed after completionHandlerLocations is done") 
      if error != nil { 
       self.alertError("Reverse geocoder failed with error" + (error?.localizedDescription)!) 
       return 
      } 

      if placemarks!.count > 0 { 
       let pm = placemarks![0] 

       let country = pm.country 
       let city = pm.locality 


       if (!cities.contains(city!)) { 
        cities.append(city!) 
       } 

       if (!countries.contains(country!)) { 
        countries.append(country!) 
       } 
      } 
      else { 
       self.alertError("Fail to perform reverse geo location") 
      } 
     }) 
    } 
    // THIS IS WILL EXECUTED FIRST 
    completionHandlerLocations(cities, countries) 
} 
+0

一つの可能​​な解決策は、ディスパッチグループを作成することです、それぞれを持っています内部ブロックはディスパッチグループに入り、離れると、最終的なcompletionHandlerLocations()を呼び出します。例:http://jordansmith.io/dispatch-groups-in-swift-3/ –

+0

ありがとう@i_am_jorf。できます。 – nsutanto

答えて

0

が言及しますi-am-jorf として、あなたはDispatchGroupを作成することができますし、すべての逆ジオコーディング作業が完了したときに通知を待つ:

private func performReverseGeoLocation(completionHandlerLocations: @escaping (_ cities: [String], _ countries: [String]) -> Void) { 
    let group = DispatchGroup() 

    var cities = [String]() 
    var countries = [String]() 

    self.images.forEach { (location) in 
     group.enter() 

     let longitude = image.longitude 
     let latitude = image.latitude 
     let location = CLLocation(latitude: latitude, longitude: longitude) 

     CLGeocoder().reverseGeocodeLocation(location, completionHandler: { (placemark, error) in 
      // do all your checks... 
      if placemark != nil && placemark!.count > 0 { 
       cities.append(placemark!.first!.locality!) 
       countries.append(placemark!.first!.country!) 
      } 

      group.leave() 
     }) 
    } 

    group.notify(queue: DispatchQueue.main) { 
     completionHandlerLocations(cities, countries) 
    } 
} 
+0

ありがとうございます。できます。私はDispatchGroupが参照カウンタのようなものだと思いますか?私たちはenter()を呼び出してx回を離れるので... – nsutanto

1

あなたはこのような何かを行うことができます。行うための最も簡単な方法です

var count = 0 

for image in self.images { 
    ... 
    CLGeocoder().reverseGeocodeLocation(location) { 
      // get result 

      counter ++ 

      if count == self.images.count { // finish all requests 
       completionHandlerLocations(cities, countries) 
      } 

    } 
} 

+0

Daniel Tran。提案していただきありがとうございます。しかし何らかの理由でそれはうまくいかない。 forループは続行され、completionHandlerLocationはx回呼び出されます。ここで、xはself.images.countです。 – nsutanto

関連する問題