在我的一个应用程序中,我需要添加一项功能,以按名称查找城市。我正在使用它CLGeocoder来实现,并且我希望它具有与iOS天气应用程序相同的行为。
CLGeocoder
下面是我的代码:
CLGeocoder().geocodeAddressString(searchBar.text!, completionHandler:{ (placemarks, error) -> Void in guard let nonNilMarks = placemarks else {return} for placemark in nonNilMarks { print("locality: \(placemark.locality)") print("name: \(placemark.name)") print("country: \(placemark.country)") print("formatted address: \(placemark.addressDictionary)") } })
在大多数情况下,它工作得很好。但是,最近我发现某些情况下失败了。以下是一些示例的输出:
locality: Optional("Milan") name: Optional("Milan") country: Optional("Italy") formatted address: Optional([SubAdministrativeArea: Milan, State: Lombardy, CountryCode: IT, Country: Italy, Name: Milan, FormattedAddressLines: ( Milan, Italy ), City: Milan])
这是正确的输出
得克萨斯州有一个小镇叫意大利。如果输入“意大利,TX”,则输出为:
locality: Optional("Italy") name: Optional("Italy") country: Optional("United States") formatted address: Optional([SubAdministrativeArea: Ellis, State: TX, CountryCode: US, Country: United States, Name: Italy, FormattedAddressLines: ( "Italy, TX", "United States" ), City: Italy])
当我只输入“意大利”时,我只会得到该国家的地标:
locality: nil name: Optional("Italy") country: Optional("Italy") formatted address: Optional([CountryCode: IT, Name: Italy, FormattedAddressLines: ( Italy ), Country: Italy])
这与“意大利德克萨斯州”的情况类似:
locality: Optional("Singapore") name: Optional("Singapore") country: Optional("Singapore") formatted address: Optional([City: Singapore, CountryCode: SG, Name: Singapore, State: Singapore, FormattedAddressLines: ( Singapore, Singapore ), Country: Singapore])
再次,似乎类似于“意大利”的情况。它只会找到一个国家:
locality: nil name: Optional("Singapore") country: Optional("Singapore") formatted address: Optional([CountryCode: SG, Name: Singapore, FormattedAddressLines: ( Singapore ), Country: Singapore])
在这个阶段,我可能会geocodeAddressString:停止搜索是否找到名称等于搜索参数的国家/地区,因此我尝试将代码更改为:
geocodeAddressString:
let addrDict = [kABPersonAddressCityKey as NSString: searchBar.text!] CLGeocoder().geocodeAddressDictionary(addrDict, completionHandler:{ (placemarks, error) -> Void in print(placemarks) })
我认为通过将搜索词限制为城市名称,我会得到正确的结果。不幸的是,我的行为完全相同!
而 THEN 我意识到,我不仅案件的问题时,城市的名字等于国家名称。
locality: nil name: Optional("Tokyo") country: Optional("Japan") formatted address: Optional([CountryCode: JP, Name: Tokyo, State: Tokyo, FormattedAddressLines: ( Tokyo, Japan ), Country: Japan])
不仅可以CLGeocoder忽略结果(例如在“意大利”的情况下),而且还可以告诉我,某个地方locality实际上没有时间(我相信上一次我查看地图时东京仍然是一座城市! )。
locality
有谁知道我如何解决这些问题?
Weather应用程序以某种方式做到了-在那里搜索“新加坡”或“意大利”会给出正确的结果。我将不胜感激!
PS:尽管我使用的是Swift,但我添加了Objective-C作为标记,因为我认为这个问题并非特定于Swift。
您所显示的用法是完全正确的,我认为您无法采取其他措施来改善结果。仍然只是一些复杂的算法,试图根据一组规则和一些假设对结果进行排序。
很难过,我完全理解您的无奈,因为我去过那里并且做到了。问题在于,地理编码数据库显然不完整,苹果不是领导该领域的公司- Google是。在这里,您可以看到从引入Geocoder时获得的技术注释,其中说仍然存在不支持或仅部分支持的国家/地区。
因此,我对您的建议是,如果您想获得最佳结果(尽管仍然不能保证失败),请切换到Google Geolocation。对于相当数量的请求,它是免费的,此后则花费很少的钱。根据我的经验,所有基本搜索的成功率都在99%左右,只有您提供更多信息,它才会变得更好。API选项也相当广泛。
希望它至少可以有所帮助。
编辑:我写完这篇文章后,我做了一些研究,似乎我不是唯一提出此声明的人(还包括相同的不受支持的链接)。