CoreLocation SDK中CLGeocoder反向地理编码locality字段异常排查
CLGeocoder反向地理编码locality字段不符合预期的问题
代码示例
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: coord.latitude, longitude: coord.longitude)) { [weak self] placeMarks, error in print("PLACEMARKSFIRST:") print(placeMarks?.first) self?.geoCodeCounter += 1 guard let place = placeMarks?.first else { self?.selectionSubject.accept(nil) self?.geoCodeAddress() return } print("PLACEMARKSFIRST:") print(placeMarks?.first) self?.geoCodeCounter += 1 guard let place = placeMarks?.first else { self?.selectionSubject.accept(nil) self?.geoCodeAddress() return } print("PLACE:") print(place) print(place.administrativeArea) print(place.subAdministrativeArea) print(place.locality) print(place.subLocality) print(place.thoroughfare) print(place.subThoroughfare) self?.geoAdministrativeArea = place.administrativeArea ?? "" self?.geoSubAdministrativeArea = place.subAdministrativeArea ?? "" self?.geoLocality = place.locality ?? "" self?.geoSubLocality = place.subLocality ?? "" self?.geoThoroughfare = place.thoroughfare ?? "" self?.geoSubThoroughfare = place.subThoroughfare ?? "" }
调试输出
PLACE: Darüşşafaka Cd. 5/2, Darüşşafaka Cd. 5/2, 34457 Sarıyer İstanbul, Türkiye @ <+41.12570667,+29.02811721> +/- 100.00m, region CLCircularRegion (identifier:'<+41.12570100,+29.02817000> radius 70.68', center:<+41.12570100,+29.02817000>, radius:70.68m)
Optional("İstanbul")
Optional("Sarıyer")
Optional("Sarıyer")
Optional("Çamlıtepe")
Optional("Darüşşafaka Cd.")
Optional("5/2")
问题描述
如上述内容所示,place的描述文本中包含Darüşşafaka,但place.locality返回的是Sarıyer,预期locality应为Darüşşafaka。请问该问题是否为CLGeocoder库的Bug?如何修复此问题?
问题分析与解决方案
问题分析
这并不是CLGeocoder的Bug,而是CLPlacemark的字段严格遵循地理行政层级定义:
locality对应的是次级行政单元(在土耳其的地理体系中,Sarıyer是伊斯坦布尔下辖的正式行政区,属于locality层级)- 你看到的
Darüşşafaka是街道名称,对应place.thoroughfare字段(调试输出中该字段已返回Darüşşafaka Cd.)
place的description文本是多字段拼接的完整地址,因此会包含Darüşşafaka,但它本身不属于locality的层级范畴。
修复方案
根据你的业务需求,可以选择以下方式处理:
- 直接利用
thoroughfare字段:如果只需要Darüşşafaka,可对place.thoroughfare的结果做简单截取,比如移除后缀" Cd.":
if let thoroughfare = place.thoroughfare { let targetName = thoroughfare.replacingOccurrences(of: " Cd.", with: "") print(targetName) // 输出 Darüşşafaka }
- 解析
addressDictionary:CLPlacemark的addressDictionary属性包含更详细的地址组件,可遍历查找所需内容:
if let addressDict = place.addressDictionary as? [String: Any] { // 打印所有地址组件,按需提取 print(addressDict) }
- 切换第三方地理编码服务:如果CLGeocoder的层级划分无法满足需求,可考虑使用其他地理编码服务,这类服务通常支持更灵活的地址组件提取。
内容的提问来源于stack exchange,提问作者yigitozdamar
相关产品推荐
相关产品推荐

