2016-02-20 4 views
0

Фон: У меня есть список контактов, которые извлекаются в асинхронной очереди из базы данных, основанной на облаке. После этого я отправлю обратно в основную очередь и покажу эти контакты в TableView.Преобразование асинхронно большого количества данных GPS в город/страну

Помимо имен и других деталей, каждый контактный объект имеет свойства координат GPS (широта и долгота). Я хочу использовать эти координаты GPS для извлечения имени города и страны каждого контакта и обновления TableView, отображающего эту информацию на локальном языке устройства, которое пользователь имеет.

Проблема: Проблема, которую я пытаюсь преодолеть, состоит в том, что у меня есть несколько сотен контактов. Сначала я использовал параллельные очереди для получения строк города/страны. Но я приостановил приложение в XCode и понял, что создано 300 новых потоков. Поэтому я изменил код, запускающий каждый поиск в городе/стране в той же последовательности.

Проблема в том, что только около 50 контактов данные обновляются. Я не знаю, почему и не уверен, даже если очередь последовательна. Отладка показывает, что все еще создано более 100 серийных очередей. В тот момент я ожидал одного. Что я делаю не так? Благодаря

код для класса, в котором у меня есть TableView выглядит следующим образом:

dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.rawValue), 0)) { 

      // get or update the contactsList 
      activeUser.contactsList.getAllContacts() 

      // once we have the contacts we go back to the main queue 
      dispatch_async(dispatch_get_main_queue()) { 
      // and refresh tableview to show the contacts 
      self.tableView.reloadData() 


      // now we refresh the locations of the contacts 
      for index in 0...activeUser.contactsList.listOfContacts.count 
      { 

      // set local variables for lat and long        
      let lat = activeUser.contactsList.listOfContacts[index].latitude 
      let long = activeUser.contactsList.listOfContacts[index].longitude 

      // call location service method with completion handler 
      MyLocationServices().updateLocationToLocalLanguage(lat, longitude: long, completionHandler: 
      { (city, country) ->() in 
       // update contact's details 
       activeUser.contactsList.listOfContacts[index].city = city 
       activeUser.contactsList.listOfContacts[index].country = country 
       // refresh each time the table to show updated contact data 
       self.tableView.reloadData() 
       }) 
      } 
    } 

метод в классе MyLocationServices выглядит следующим образом:

func updateLocationToLocalLanguageDispatched(latitude: String, longitude: String, completionHandler: (city: String, country: String) ->()) 
{ 
    let serialQ = dispatch_queue_create("AddressUpdateQ", DISPATCH_QUEUE_SERIAL) 

    dispatch_async(serialQ) 
    { 
     var cityString = "NA" 
     var countryString = "NA" 
     let group = dispatch_group_create() 
     dispatch_group_enter(group) 

     let location = CLLocation(latitude: Double(latitude)!, longitude: Double(longitude)!) 

     self.geocoder.reverseGeocodeLocation(location) 
     { 
      (placemarks, error) -> Void in 

      if let placemarks = (placemarks as [CLPlacemark]!) where placemarks.count > 0 
      { 

       let placemark = placemarks[0] 
       if ((placemark.addressDictionary!["City"]) as? String != nil) { cityString = ((placemark.addressDictionary!["City"]) as? String)! } 
       if ((placemark.addressDictionary!["Country"]) as? String != nil) { countryString = ((placemark.addressDictionary!["Country"]) as? String)! } 
      } 
      dispatch_group_leave(group) 

     } 

     dispatch_group_wait(group, DISPATCH_TIME_FOREVER) 
     dispatch_async(dispatch_get_main_queue()) 
     { 
       completionHandler(city: cityString, country: countryString) 
     } 


    } 

} 

ответ

0

I решили проблему и документировали надежду, что она полезна, если другие сталкиваются с аналогичными проблемами.

(1) Последовательная очередность: Я понял, что инициализация последовательной очереди не должна происходить внутри метода, но приложить цикл for. Таким образом, следующий код должен быть удален из метода и помещен вокруг цикла for. Но это не решает тот факт, что я получаю только 50 результатов и ничего для остальных GPS-данных контактов.

let serialQ = dispatch_queue_create("AddressUpdateQ", DISPATCH_QUEUE_SERIAL); 

    dispatch_async(serialQ) 
    { [for index....] } 

(2) Расположение: Вторая проблема связана с геокодировщиком Apple, которая происходит в Интернете. Официально количество запросов ограничено. В documentation указано, что один «не должен отправлять более одного запроса на геокодирование в минуту».

Применения должны быть осведомлены о том, как они используют геокодирование. Геокодирование запросов ограничено по скорости для каждого приложения, поэтому слишком много запросов в может привести к сбою некоторых запросов.

Проверка кода ошибки Получаю, это Error Domain=kCLErrorDomain Code=2. Кажется, что услуга отрицается, и я не могу делать дальнейшие запросы.

(3) Решения: На мой взгляд, есть два решения. Один из них - обновить 30 или около того пользователей, подождать некоторое время, а затем отправить следующую очередность, чтобы снова получить некоторые данные. Второе решение - жить со всеми данными на английском языке, создать строку, которую каждый пользователь сохраняет в облаке.Таким образом, для других пользователей, получающих контакты, это просто вопрос выборки строки из базы данных, а не проверка данных GPS «на лету».