2016-08-08 59 views
1

我想寫一個函數來反轉地理編碼的位置並將結果字符串分配給一個變量。繼this後我得到了這樣的事情:無法從CLGeocoder返回字符串reverseGeocodeLocation

extension CLLocation { 

    func reverseGeocodeLocation(completion: (answer: String?) -> Void) { 

     CLGeocoder().reverseGeocodeLocation(self) { 

      if let error = $1 { 
       print("[ERROR] \(error.localizedDescription)") 
       return 
      } 

      if let a = $0?.last { 
       guard let streetName = a.thoroughfare, 
        let postal = a.postalCode, 
        let city = a.locality else { return } 

       completion(answer: "[\(streetName), \(postal) \(city)]") 
      } 

     } 
    } 
} 

對於調用這個函數我剛剛拿到了這樣的事情:

location.reverseGeocodeLocation { answer in 
    print(answer) 
} 

而是我想要的answer字符串值賦給一個變量,我不知道如何從關閉中傳遞數據。做這種事情的最佳方式是什麼?

回答

3

問題是它異步運行,所以你不能返回值。如果要更新一些屬性或變量,這樣做的正確的地方是在你提供的方法關閉,例如:

var geocodeString: String? 

location.reverseGeocodeLocation { answer in 
    geocodeString = answer 
    // and trigger whatever UI or model update you want here 
} 

// but not here 

關閉completion處理模式的整個目的是首選提供異步檢索的數據的方式。

+0

You posted回答,而我正在撰寫我的。你在幾秒鐘之內擊敗了我...... :) –

+0

哈哈。抱歉。也許堆棧溢出應該有一個功能,你知道,如果有人正在輸入一個答案(有點像Skype或一些聊天平臺)... – Rob

+0

謝謝!解決了問題unlike️ –

1

簡答:你不能。這不是異步編程的工作原理。在答案可用之前,功能reverseGeocodeLocation立即返回。在將來的某個時候,地理編碼結果將變爲可用,並且在發生這種情況時,您的關閉中的代碼將被調用。那就是當你對你的答案做些什麼的時候。你可以編寫閉包來在標籤中安裝答案,更新表格視圖或其他行爲。 (我不記得是否在主線程或後臺線程上調用了地理編碼方法的閉包,如果它們在後臺線程中調用,則需要將您的UI調用包裝在dispatch_async(dispatch_get_main_queue())中。)

+0

FWIW,與許多異步API方法不同,使用'reverseGeocodeLocation'您不必擔心將任何事情分派到主隊列。正如[文檔說](https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLGeocoder_class/index.html#//apple_ref/occ/instm/CLGeocoder/reverseGeocodeLocation:completionHandler :),「您的完成處理程序塊將在主線程上執行。「但是你關於主隊列的觀點是非常好的,因爲這是許多其他帶有完成處理程序的異步方法的問題。 – Rob

+1

@Rob,謝謝你澄清。我不記得'reverseGeocodeLocation'如何處理它的關閉,並且當我發佈我的答案時沒有時間查看它。 –