2017-02-09 16 views
1

GeoCodeリクエストは一度に1つしか実行できず、非同期であるため、直前のGeoCodeリクエストが終了するとすぐに次のリクエストを開始する必要があります。Swift:ジオコーディングの再帰を伴う非同期ループ

func one() { 
     let geocoder = CLGeocoder() 
     let one = myPlacesFakeData[0] 

     geocoder.geocodeAddressString(one.address, completionHandler: { (placemarks, error) in 
      if let error = error { 
       print("Unable to Reverse Geocode Location (\(error))") 
      } else { 
       if let placemarks = placemarks, let placemark = placemarks.first { 
        myPlacesFakeData[0].latitude = placemark.location?.coordinate.latitude 
        myPlacesFakeData[0].longitude = placemark.location?.coordinate.longitude 
       } else { 
        print("No Matching Address Found") 
       } 
      } 

      self.two() 
     }) 
    } 

    func two() { 
     let geocoder = CLGeocoder() 
     let two = myPlacesFakeData[1] 

     geocoder.geocodeAddressString(two.address, completionHandler: { (placemarks, error) in 
      if let error = error { 
       print("Unable to Reverse Geocode Location (\(error))") 
      } else { 
       if let placemarks = placemarks, let placemark = placemarks.first { 
        myPlacesFakeData[1].latitude = placemark.location?.coordinate.latitude 
        myPlacesFakeData[1].longitude = placemark.location?.coordinate.longitude 
       } else { 
        print("No Matching Address Found") 
       } 
      } 
      self.three() 
     }) 
    } 

    func three() { 
     let geocoder = CLGeocoder() 
     let three = myPlacesFakeData[2] 

     geocoder.geocodeAddressString(three.address, completionHandler: { (placemarks, error) in 
      if let error = error { 
       print("Unable to Reverse Geocode Location (\(error))") 
      } else { 
       if let placemarks = placemarks, let placemark = placemarks.first { 
        myPlacesFakeData[2].latitude = placemark.location?.coordinate.latitude 
        myPlacesFakeData[2].longitude = placemark.location?.coordinate.longitude 
       } else { 
        print("No Matching Address Found") 
       } 
      } 

     }) 
    } 

しかし、これはゲットーであり、私がGeoCodeにしようとしている場所がちょうど3つあることに依存しています。

私は再帰関数とカウンタが必要だと思いますが、これを書く方法はわかりません。どんな助けでも大歓迎です。

答えて

3

ここには1つのアプローチを示す遊び場があります。すべてのアドレスがジオコーディングされたら、最終的に補完ハンドラを呼び出す結果を蓄積し、自身を呼び出す関数を使用できます。より良いタイプのエラー処理とラッピングを行うと、より良い結果が得られますが、それは良い出発点です!

//: Playground - noun: a place where people can play 

import Cocoa 
import CoreLocation 
import PlaygroundSupport 

PlaygroundPage.current.needsIndefiniteExecution = true 

func geoCode(addresses: [String], results: [CLPlacemark] = [], completion: @escaping ([CLPlacemark]) -> Void) { 
    guard let address = addresses.first else { 
     completion(results) 
     return 
    } 

    let geoCoder = CLGeocoder() 
    geoCoder.geocodeAddressString(address) { placemarks, error in 

     var updatedResults = results 

     if let placemark = placemarks?.first { 
      updatedResults.append(placemark) 
     } 

     let remainingAddresses = Array(addresses[1..<addresses.count]) 

     geoCode(addresses: remainingAddresses, results: updatedResults, completion: completion) 
    } 
} 

let addresses = ["1600 Pennsylvania Ave NW, Washington, DC 20500", "1 Infinite Loop, Cupertino, CA"] 

geoCode(addresses: addresses) { results in 
    print("Got back \(results.count) results") 
} 
+1

Andrew、ありがとうございました。完璧に働いた。 –