2016-09-23 152 views
1

我想了解for循環中有完成處理程序方法的行爲。Swift:在for循環中調用完成處理程序方法

請參閱下面的示例,我試圖獲取2個地址的緯度/經度座標。

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 

輸出是這樣的

0 
1 
Address = 1 Infinite Loop, Cupertino 

我很奇怪,爲什麼沒有在代碼打印的其他地址。第二個循環沒有調用geocodeAddressString方法。假定在for循環結束後應用程序執行沒有結束,我還做了很多其他的事情。

+0

是真正的輸出還是你輸入了?不應該最後一行看起來像'地址=東西' – Fonix

+0

您發佈的代碼沒有直接連接到輸出,請使用從代碼和控制檯複製粘貼;你也打印'地址',這是什麼? –

+0

更新了代碼和輸出。 – sysuser

回答

1

說明:

  • 有for循環它運行N次(addressArray.count)。
  • 在每次迭代期間,都會進行地理編碼請求。
  • 獲取地點標記需要一些時間。
  • 這是一個異步方法,因此它不會阻止執行(意味着循環繼續運行,不會等到地理位置請求完成)。
  • 當特定迭代的地理編碼請求完成時,它會執行完成處理程序。

問題:

  • 由於完成順序沒有保證,最好是使用字典代替陣列。
  • 請勿使用數組,因爲完成順序可能不是順序的。
  • 例如,第1個請求可能在第2個請求完成後完成。

解決方案:

  • 對於給定的整數索引,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 
       } 
      } 
     } 
    } 
} 
+0

謝謝,我會用字典。我主要想知道異步循環請求的行爲。 – sysuser