一尘不染

当城市名称等于某个国家的名称时(不仅是),CLGeocoder返回错误的结果

swift

在我的一个应用程序中,我需要添加一项功能,以按名称查找城市。我正在使用它CLGeocoder来实现,并且我希望它具有与iOS天气应用程序相同的行为。

下面是我的代码:

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

在大多数情况下,它工作得很好。但是,最近我发现某些情况下失败了。以下是一些示例的输出:

搜索“米兰”-WORKS

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

这是正确的输出

搜索“德克萨斯州意大利”-WORKS

得克萨斯州有一个小镇叫意大利。如果输入“意大利,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])

搜索“新加坡,新加坡”-WORKS

这与“意大利德克萨斯州”的情况类似:

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:停止搜索是否找到名称等于搜索参数的国家/地区,因此我尝试将代码更改为:

let addrDict = [kABPersonAddressCityKey as NSString: searchBar.text!]
CLGeocoder().geocodeAddressDictionary(addrDict, completionHandler:{ (placemarks, error) -> Void in
    print(placemarks)
})

我认为通过将搜索词限制为城市名称,我会得到正确的结果。不幸的是,我的行为完全相同!

THEN 我意识到,我不仅案件的问题时,城市的名字等于国家名称。

正在搜索“东京”-EPIC FAIL

locality: nil
name: Optional("Tokyo")
country: Optional("Japan")
formatted address: Optional([CountryCode: JP, Name: Tokyo, State: Tokyo, FormattedAddressLines: (
    Tokyo,
    Japan
), Country: Japan])

结论

不仅可以CLGeocoder忽略结果(例如在“意大利”的情况下),而且还可以告诉我,某个地方locality实际上没有时间(我相信上一次我查看地图时东京仍然是一座城市!
)。

有谁知道我如何解决这些问题?

Weather应用程序以某种方式做到了-在那里搜索“新加坡”或“意大利”会给出正确的结果。我将不胜感激!

PS:尽管我使用的是Swift,但我添加了Objective-C作为标记,因为我认为这个问题并非特定于Swift。


阅读 171

收藏
2020-07-07

共1个答案

一尘不染

您所显示的用法是完全正确的,我认为您无法采取其他措施来改善结果。仍然只是一些复杂的算法,试图根据一组规则和一些假设对结果进行排序。

很难过,我完全理解您的无奈,因为我去过那里并且做到了。问题在于,地理编码数据库显然不完整,苹果不是领导该领域的公司-
Google是。在这里,您可以看到从引入Geocoder时获得的技术注释,其中说仍然存在不支持或仅部分支持的国家/地区。

因此,我对您的建议是,如果您想获得最佳结果(尽管仍然不能保证失败),请切换到Google
Geolocation。对于相当数量的请求,它是免费的,此后则花费很少的钱。根据我的经验,所有基本搜索的成功率都在99%左右,只有您提供更多信息,它才会变得更好。API选项也相当广泛。

以下是针对地理编码和反向地理编码的开发人员文档的链接:https
//developers.google.com/maps/documentation/geocoding/intro
https://developers.google.com/maps/documentation/javascript/examples/geocoding-
逆转

希望它至少可以有所帮助。

编辑:我写完这篇文章后,我做了一些研究,似乎我不是唯一提出此声明的人(还包括相同的不受支持的链接)。

2020-07-07