地理编码报错:kCLErrorDomain错误码1与8排查求助
问题:Firestore地址地理编码时出现kCLErrorDomain错误
从Firestore获取所有用户地址并尝试地理编码为经纬度时,出现以下错误:
2022-07-26 15:40:39.676845-0400 Polygon[96779:3864577] [MKCoreLocationProvider] CLLocationManager(<CLLocationManager: 0x6000004c2c90>) for <MKCoreLocationProvider: 0x6000034f0870> did fail with error: Error Domain=kCLErrorDomain Code=1 "(null)"
以及
Error Error Domain=kCLErrorDomain Code=8 "(null)"
单个地址在其他项目中可正常地理编码,但当前代码运行出错,完整代码如下:
import SwiftUI import MapKit import CoreLocationUI import Firebase struct Place: Identifiable { let id = UUID() var name: String var coordinate: CLLocationCoordinate2D } struct MapView: View { var empireStateBuilding = Place(name: "Empire State Building", coordinate: CLLocationCoordinate2D(latitude: 40.748433, longitude: -73.985656)) @StateObject private var viewModel = ContentViewModel() @State var address = "" @State var addresses:[String] = [] let geocoder = CLGeocoder() @State private var result = "result of lat & long" @State private var lat = 0.0 @State private var long = 0.0 @State private var country = "country name" @State private var state = "state name" @State private var zip = "zip code" var body: some View { NavigationView { ZStack (alignment: .bottom) { Map(coordinateRegion: $viewModel.region, showsUserLocation: true) .ignoresSafeArea() .tint(.pink) LocationButton(.currentLocation) { viewModel.requestAllowOnceLocationPermission() } .foregroundColor(.white) .cornerRadius(8) .labelStyle(.iconOnly) .symbolVariant(.fill) .tint(.pink) .padding(.bottom) .padding(.trailing, 300) Button { print(address) geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in if((error) != nil){ print("Error", error ?? "") } if let placemark = placemarks?.first { if let coordinates:CLLocationCoordinate2D = placemark.location.coordinate { print("Lat: \(coordinates.latitude) -- Long: \(coordinates.longitude)") //added code result = "Lat: \(coordinates.latitude) -- Long: \(coordinates.longitude)" lat = coordinates.latitude long = coordinates.longitude } } }) } label: { Image(systemName: "arrow.clockwise") } .padding(.leading, 300) .padding(.bottom) .cornerRadius(8) Text("\(result)") } List(0..<addresses.count, id: \.self) {i in Text(addresses[i]) } } .onAppear(perform: { downloadServerData() }) } func downloadServerData() { let db = Firestore.firestore() db.collection("UserInfo").addSnapshotListener {(snap, err) in if err != nil{ print("There is an error") return } for i in snap.documentChanges { let documentId = i.document.documentID if let address = i.document.get("address") as? String { DispatchQueue.main.async { addresses.append("\(address)") print(address) } } } } } } struct AnnotatedItem: Identifiable { let id = UUID() var name: String var coordinate: CLLocationCoordinate2D } struct MapView_Previews: PreviewProvider { static var previews: some View { MapView() } } //LocationButton final class ContentViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { @Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 40, longitude: 120), span: MKCoordinateSpan(latitudeDelta: 100, longitudeDelta: 100)) let locationManager = CLLocationManager() override init() { super.init() locationManager.delegate = self } func requestAllowOnceLocationPermission() { locationManager.requestLocation() } func locationManager( _ _manager:CLLocationManager, didUpdateLocations locations: [CLLocation]){ guard let latestLocation = locations.first else { // show an error return } DispatchQueue.main.async{ self.region = MKCoordinateRegion( center: latestLocation.coordinate, span:MKCoordinateSpan(latitudeDelta:0.05, longitudeDelta:0.05)) } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print(error.localizedDescription) } } struct MapView1_Previews: PreviewProvider { static var previews: some View { MapView() } }
错误原因及修复建议
1. 位置权限配置缺失
- Code=1 对应
kCLErrorDenied,表示位置权限被拒绝。当前代码直接调用requestLocation(),但未提前请求权限,导致权限被默认拒绝。
修复:在ContentViewModel的权限请求方法中添加状态检查:
同时必须在func requestAllowOnceLocationPermission() { switch locationManager.authorizationStatus { case .notDetermined: locationManager.requestWhenInUseAuthorization() case .authorizedWhenInUse, .authorizedAlways: locationManager.requestLocation() default: // 可弹窗提示用户前往设置开启权限 break } }Info.plist中添加NSLocationWhenInUseUsageDescription键,填写权限申请说明文本,否则权限请求会直接失败。
2. 地理编码目标地址为空
- Code=8 对应
kCLErrorGeocodeFoundNoResult,当前代码中按钮点击时使用的address变量始终为空字符串(从未被赋值为Firestore获取的地址),导致地理编码请求无结果。
修复:改为遍历addresses数组批量处理地址:Button { for addr in addresses { guard !addr.isEmpty else { continue } geocoder.geocodeAddressString(addr, completionHandler: {(placemarks, error) -> Void in if let error = error { print("地址\(addr)编码失败:", error) return } if let placemark = placemarks?.first, let coordinates = placemark.location?.coordinate { print("地址\(addr)坐标: Lat: \(coordinates.latitude) -- Long: \(coordinates.longitude)") // 此处可将坐标存入数组或更新UI } }) } } label: { Image(systemName: "arrow.clockwise") }
3. CLGeocoder实例生命周期不稳定
- 在
MapView结构体中直接声明CLGeocoder,SwiftUI视图会频繁重建,可能导致地理编码请求被中断。
修复:将geocoder移至ContentViewModel中作为类属性:
之后在View中通过final class ContentViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { // ... 其他属性 let geocoder = CLGeocoder() // ... 其他方法 }viewModel.geocoder调用。
4. Firestore快照监听重复添加地址
addSnapshotListener会在数据变化时多次触发,当前代码每次触发都会追加所有新文档的地址,导致数组重复。
修复:只处理新增类型的文档变更:for i in snap.documentChanges { guard i.type == .added else { continue } // 仅处理新增文档 if let address = i.document.get("address") as? String { DispatchQueue.main.async { addresses.append(address) print(address) } } }
5. CLLocationManagerDelegate方法签名错误
locationManager( _ _manager:CLLocationManager, didUpdateLocations locations: [CLLocation])的参数名有多余下划线,导致系统无法正确调用该方法,位置更新失败。
修复:修正方法签名:func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let latestLocation = locations.first else { return } DispatchQueue.main.async{ self.region = MKCoordinateRegion( center: latestLocation.coordinate, span:MKCoordinateSpan(latitudeDelta:0.05, longitudeDelta:0.05)) } }
内容的提问来源于stack exchange,提问作者user19620292
相关产品推荐
相关产品推荐

