将异步较大的GPS数据转换为城市/国家/地区



>背景:我有一个联系人列表,这些联系人是从基于云的数据库中的异步队列中检索的。 完成后,我调度回主队列并在 TableView 中显示这些联系人。

除了名称和其他详细信息外,每个联系人对象还具有 GPS 坐标属性(纬度和经度)。我想使用这些 GPS 坐标来检索每个联系人的城市和国家/地区的名称,并更新以用户拥有的设备本地语言显示该信息的 TableView。

问题:我试图克服的问题是我有几百个联系人。 最初,我使用并发队列来获取城市/国家/地区字符串。 但我在 XCode 中暂停了应用程序,并意识到创建了 300+ 线程的灾难。 所以我更改了在同一串行队列上运行城市/国家/地区每次查找的代码。

现在的问题是,只有大约50个联系人的数据才会更新。我不知道为什么,也不确定队列是否是串行的。 调试显示仍然创建了 100+ 个"串行队列"。 我当时期待一个。 我做错了什么? 谢谢

我在其中拥有表视图的类的代码如下:

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

类中的方法如下所示:

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

    }
}

我已经解决了这个问题并记录下来,希望在其他人遇到类似问题时有所帮助。

(1)串行队列:我已经意识到串行队列启动不应该发生在方法中,而应该包含for循环。 因此,应从方法中删除以下代码并放在 for 循环周围。但这并不能解决这样一个事实,即我只得到大约 50 个结果,而联系人的剩余 GPS 数据一无所获。

let serialQ = dispatch_queue_create("AddressUpdateQ", DISPATCH_QUEUE_SERIAL);
    dispatch_async(serialQ)
    { [for index....] }

(2)位置:第二个问题与苹果的地理编码器有关,它发生在网上。官方认为,请求的数量是有限的。文件指出一个"每分钟不应发送多个地理编码请求"。

应用程序应注意他们如何使用地理编码。地理编码 每个应用的请求都有速率限制,因此在 短时间可能会导致某些请求失败。

检查我得到的错误代码,它Error Domain=kCLErrorDomain Code=2.该服务似乎被拒绝了,我无法提出进一步的请求。

(3)解决方案:在我看来有两种解决方案。一种是更新 30 个左右的用户,等待一段时间,然后调度另一个队列以再次获取一些数据。 第二种解决方案是接受所有数据都是英文的,制作一个字符串,每个用户都保存在云中。 因此,对于检索联系人的其他用户来说,只需从数据库中获取字符串,而不是"即时"检查GPS数据。

最新更新