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

And*_*huk 16 objective-c ios clgeocoder swift swift2

在我的一个应用程序中,我需要添加一个按名称查找城市的功能.我正在使用它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)")
    }
})
Run Code Online (Sandbox Code Playgroud)

它在大多数情况下都能很好地工作.但是,我最近注意到一些失败的情况.以下是一些示例的输出:

寻找'米兰' - 工作

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])
Run Code Online (Sandbox Code Playgroud)

这是正确的输出

寻找'意大利,德克萨斯州' - 工作

德克萨斯州有一个叫意大利的小镇.如果我键入'Italy,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])
Run Code Online (Sandbox Code Playgroud)

寻找'意大利' - 失败

当我输入"意大利"时,我只获得该国家的地方标记:

locality: nil
name: Optional("Italy")
country: Optional("Italy")
formatted address: Optional([CountryCode: IT, Name: Italy, FormattedAddressLines: (
    Italy
), Country: Italy])
Run Code Online (Sandbox Code Playgroud)

寻找'新加坡,新加坡' - WORKS

这与'Italy,TX'的情况类似:

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])
Run Code Online (Sandbox Code Playgroud)

正在寻找'新加坡' - 失败

再次,似乎与'意大利'的情况类似.它只找到一个国家:

locality: nil
name: Optional("Singapore")
country: Optional("Singapore")
formatted address: Optional([CountryCode: SG, Name: Singapore, FormattedAddressLines: (
    Singapore
), Country: Singapore])
Run Code Online (Sandbox Code Playgroud)

初步猜测

在这个阶段我可能会geocodeAddressString:停止搜索它是否找到一个名称等于搜索参数的国家,所以我尝试将我的代码更改为:

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

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

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

寻找'东京' - EPIC失败

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

结论

不仅可以CLGeocoder省略结果(比如'意大利'),但它也可以告诉我一个地方没有locality时间,事实上它确实如此(我相信上次我查了一张地图东京还是一个城市! ).

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

天气应用程序以某种方式做到了 - 搜索'新加坡'或'意大利'那里给出了正确的结果.我将不胜感激任何帮助!

PS虽然我正在使用Swift,但我将Objective-C添加为标签,因为我认为这个问题不是特定于Swift的.

Jir*_*cak 7

使用你所展示的是完全正确的,我认为你无法做任何其他事情来改善结果.它仍然只是一些复杂的算法,试图根据规则集和一些假设对结果进行排序.

那很难过,我完全理解你的挫败感,因为我去过那里并做到了.问题在于地理编码数据库显然并不完整,而苹果并不是领导这一领域的公司 - 谷歌就是.在这里,您可以看到引入Geocoder时的技术说明,其中表示仍有国家不受支持或仅部分支持.

所以我的建议是,如果你想获得最好的结果(虽然仍然没有防止故障),请切换到Google Geolocation.对于相当多的请求它是免费的,之后它需要一些非常小的金额.根据我的经验,所有基本搜索的成功率约为99%,如果您提供更多信息,它的效果会更好.API选项也非常广泛.

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

希望它至少有一点帮助.

编辑:在我写这篇文章之后,我做了一些研究,似乎我不是唯一提出这种说法的人(也包括相同的不受支持的链接).