2016-12-15 69 views
0

我正在使用循環並對CLGeocoder進行API調用。 API調用正確的次數,但completionHandler只返回一次,用於第一次API調用,然後它不會爲其餘調用返回任何內容。API調用僅在循環中返回響應一次

dispatch_async(dispatch_get_main_queue()) 
        {        
         for shop in self.shopsList { 
          let shopAddress = shop.address 
          self.geocoder.geocodeAddressString(shopAddress, completionHandler: { (placemarks, error) in 
           if let error = error { 
            print(error) 
            return 
           } 
           if let placemarks = placemarks where placemarks.count > 0 { 
            if let location = placemarks.first?.location { 
             print("The longitude: \(location.coordinate.longitude)") 
             print("The latitude: \(location.coordinate.latitude)") 
            } 
           } 
          }) 
         } 

         self.spinner.dismiss() 
         self.categoryTableView.dataSource = self 
         self.categoryTableView.delegate = self 
         self.categoryTableView.reloadData() 
       } 

其餘調用根本不返回任何內容,甚至不輸入任何if語句。有人能告訴我我做錯了什麼嗎?

我曾試過把的結束for循環增加sleep(2),但它仍然只能返回一次

回答

1

你不準在那樣的行提交多個地址解析請求。除了第一個都可能被拒絕。

引述上CLGeocoder文檔:

應用程序應該意識到他們是如何利用地理編碼。地理編碼 請求對每個應用都是速率限制的,因此在短時間內在 內請求太多請求可能會導致某些請求失敗。 (當 超過最大速度,地址解析器返回一個錯誤的對象 與價值kCLErrorNetwork到相關的完成處理程序。) 這裏有一些經驗法則有效地使用這個類:

  • 發送至多一個用戶操作的地理編碼請求。

  • 如果用戶執行涉及對相同位置進行地理編碼的多個操作,請重複使用初始地理編碼請求 的結果,而不是爲每個操作啓動單個請求。

  • 當你想自動更新用戶的當前位置(例如,當用戶在移動時),發行新的地址解析請求僅
    當用戶移動了顯著的距離和後一段合理 量已過。例如,在典型情況下,您不應每分鐘發送一個以上的地理編碼請求。

  • 當用戶不會立即看到結果時,不要開始地理編碼請求。例如,如果 您的應用程序處於非活動狀態或在後臺,請勿開始請求。

你只能在一個時間提交一個地址解析請求,而你不應該提交超過〜1每分鐘。這樣的代碼將工作:

let arrayOfAddresses = ["123 main street denver CO", "100 W. 23rd street, NY, NY", ] 

var addressesToGeocode: [String]! 
var geocoder = CLGeocoder() //Configure the geocoder as needed. 

///Call this function to geocode your entire array of addresses. 
func geocodeArrayOfaddresses() { 
    //Copy over the array of addresses. 
    addressesToGeocode = arrayOfAddresses 
    geocodeNextAddress() 
} 

func geocodeNextAddress() { 
    guard !addressesToGeocode.isEmpty else { 
    return 
    } 
    //Pull an address out of the array. 
    let address = addressesToGeocode.removeLast() 

    //Submit a geocoding request for this address. 
    geocoder.geocodeAddressString(address) { 
    (placemarks, error) in 
    //Once we're done with the completion block, submit another geocoding 
    //request after a minute delay. 
    defer { 
     //Wait 60 seconds before geocoding the next address. 
     DispatchQueue.main.asyncAfter(wallDeadline: .now() + 60.0) { 
     self.geocodeNextAddress() 
     } 
    } 
    if let error = error { 
     print(error) 
    } 
    if let placemarks = placemarks, 
     placemarks.count > 0 { 
     if let location = placemarks.first?.location { 
     print("The longitude: \(location.coordinate.longitude)") 
     print("The latitude: \(location.coordinate.latitude)") 
     } 
    } 
    } 
} 
+0

我曾嘗試在for循環的末尾添加'sleep(2)',但它仍然只返回一次 – Bob

+0

使用sleep幾乎從來都不是一個好主意,特別是從主線程中。 rmaddy在他的回答中包含了關於如何執行多個地址解析請求的建議鏈接。至少,您需要重構代碼以提交請求並等待它完成,然後再提交下一個請求。 –

+0

使用睡眠(2)是建議我知道的建議 – Bob

0

你應該閱讀的geocodeAddressString方法(突出礦井)的文檔:

這種方法指定位置數據提交到地理編碼服務器異步和回報。您的完成處理程序塊將在主線程上執行。 發起前向地理編碼請求後,請勿嘗試發起另一個前向或反向地理編碼請求。

地理編碼請求對每個應用都是速率限制的,因此在短時間內請求太多可能會導致某些請求失敗。當超過最大速率時,地理編碼器將具有值網絡的錯誤對象傳遞給完成處理程序。

所以基本上你不能使用一個簡單的循環來產生大量的併發請求。有關一種可能的解決方案,請參閱Strategy to perform many Geocode requests

+0

我曾嘗試在for循環結尾添加'sleep(2)',但它仍然只返回一次 – Bob