2016-09-22 1 views
0

Ich versuche, Folgendes in swift zu tun: Versuche, eine Liste von Adressen in einem Array umzukehren und ihre Breiten-/Längenkoordinaten auszudrucken. Der Code, den ich habe, ist wie folgt.Swift: Asynchroner Aufruf in einer for-Schleife

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!) 
       } 
      }) 
     } 
    } 
} 

Der Code druckt nur die erste Adresse, die dekodiert wurde und nichts passiert dann.

Ich habe eine Lösung für diesen wie die folgenden ein, die den printAddressList Anruf von viewDidLoad Verfahren wie diese

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() 
    } 
} 

Selbst zu bewegen ist, obwohl die letztere Lösung funktioniert, sehe ich, dass es nicht sauber ist, würde möchte den richtigen Weg kennen, um den Code lesbar und sauber zu machen.

Antwort

3

Wie wäre es mit dieser Struktur?

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()      
} 

Es ist sehr nettes Tutorial über dispatch_group here.

+0

Zunächst einmal vielen Dank für den Vorschlag. Ich habe mehr über Versandgruppen von dem Link verstanden, den Sie angegeben haben. Aber ich konnte deine Lösung nicht verstehen. Mein Problem ist, dass die Geokodierungsmethode innerhalb der for-Schleife ist. Zu der Zeit, zu der die erste Adresse decodiert wird, hat die for-Schleife die zweite Iteration abgeschlossen. Die Frage ist, warum ich die zweite Adresse überhaupt nicht entziffern sehe (die print-Anweisung innerhalb des Geocodes in meinem Fall). Sollte ich eine while-Schleife anstelle von for-Schleife verwenden. – sysuser

+0

Ich denke, es ist egal, ob Sie For-Schleife oder While-Schleife verwenden. Wie Sie im Titel erwähnt haben, handelt es sich um einen asynchronen Aufruf, der nicht garantiert, dass die Ergebnisse des Beendigungshandlers vor dem Aufruf von printAddressList() zurückgegeben werden. Zu dem Zeitpunkt, zu dem Ihre erste Geokodierungsanforderung zurückgegeben wird, hat Ihr Programm beispielsweise bereits ein Adressarray durchlaufen und dann möglicherweise die printAddressList-Funktion ausgeführt, die keine korrekten Werte ausgibt. Aus diesem Grund denke ich, dass Sie dispatch_group verwenden müssen, damit Sie warten können, bis Sie alle gewünschten Ergebnisse vom Complete-Handler erhalten haben. – woogii

+0

True, der Dispatch-Handler mit Benachrichtigung funktioniert. – sysuser

Verwandte Themen