SwiftUI中如何通过经纬度利用PlacePicker类获取GMS位置名称
问题描述
我现有一个可通过搜索街道名称获取位置的PlacePicker组件(代码如下),希望在该类中添加giveLocationByLatLong(lat: Double, long: Double)方法,仅传入经纬度即可获取位置名称,请问该如何实现?是否可复用该类现有内容?
struct PlacePicker: UIViewControllerRepresentable { func makeCoordinator() -> GooglePlacesCoordinator { GooglePlacesCoordinator(self) } @Environment(\.presentationMode) var presentationMode @Binding var address: String @Binding var latitude: Double @Binding var longitude: Double func makeUIViewController(context: UIViewControllerRepresentableContext<PlacePicker>) -> GMSAutocompleteViewController { GMSPlacesClient.provideAPIKey("xxxx") let autocompleteController = GMSAutocompleteViewController() autocompleteController.delegate = context.coordinator let fields: GMSPlaceField = GMSPlaceField(rawValue:UInt(GMSPlaceField.name.rawValue) | UInt(GMSPlaceField.placeID.rawValue) | UInt(GMSPlaceField.coordinate.rawValue) | GMSPlaceField.addressComponents.rawValue | GMSPlaceField.formattedAddress.rawValue) autocompleteController.placeFields = fields let filter = GMSAutocompleteFilter() filter.type = .address autocompleteController.autocompleteFilter = filter return autocompleteController } func updateUIViewController(_ uiViewController: GMSAutocompleteViewController, context: UIViewControllerRepresentableContext<PlacePicker>) { } class GooglePlacesCoordinator: NSObject, UINavigationControllerDelegate, GMSAutocompleteViewControllerDelegate { var parent: PlacePicker init(_ parent: PlacePicker) { self.parent = parent } func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) { DispatchQueue.main.async { print(place.description.description as Any) self.parent.address = place.formattedAddress ?? "adresa gresita" self.parent.presentationMode.wrappedValue.dismiss() self.parent.latitude=place.coordinate.latitude self.parent.longitude=place.coordinate.longitude } } func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) { print("Error: ", error.localizedDescription) } func wasCancelled(_ viewController: GMSAutocompleteViewController) { parent.presentationMode.wrappedValue.dismiss() } } }
实现方案
完全可以复用现有类的资源(比如已配置的GMSPlacesClient),核心是调用Google Places的逆地理编码接口完成经纬度到地址名称的解析,具体实现如下:
步骤1:在PlacePicker中新增目标方法
直接在结构体中添加giveLocationByLatLong方法,利用GMSPlacesClient的逆地理编码能力:
struct PlacePicker: UIViewControllerRepresentable { // 原有代码保持不变... // 新增:经纬度转地址名称方法 func giveLocationByLatLong(lat: Double, long: Double, completion: @escaping (String?, Error?) -> Void) { // 复用原有API Key配置逻辑 GMSPlacesClient.provideAPIKey("xxxx") let targetCoordinate = CLLocationCoordinate2D(latitude: lat, longitude: long) // 复用原有字段定义,或按需精简(这里只保留地址相关字段) let requiredFields: GMSPlaceField = GMSPlaceField(rawValue: UInt(GMSPlaceField.formattedAddress.rawValue) | UInt(GMSPlaceField.name.rawValue)) GMSPlacesClient.shared().fetchPlace(fromCoordinate: targetCoordinate, placeFields: requiredFields) { place, error in DispatchQueue.main.async { if let error = error { completion(nil, error) return } // 优先返回格式化地址,无则返回地点名称 let resolvedAddress = place?.formattedAddress ?? place?.name ?? "无法获取地址" completion(resolvedAddress, nil) } } } // 原有代码保持不变... }
步骤2:复用现有资源说明
- API Key配置:直接复用原代码中
GMSPlacesClient.provideAPIKey的逻辑,无需重复初始化; - 字段定义:可以直接使用原代码中定义的
fields常量,或根据需求精简字段以减少请求数据量; - 线程处理:和原代码一致,将回调结果切回主线程,避免UI更新时的线程冲突。
调用示例
在使用PlacePicker的上下文里,可这样调用该方法:
let placePicker = PlacePicker(address: .constant(""), latitude: .constant(0), longitude: .constant(0)) placePicker.giveLocationByLatLong(lat: 39.9042, long: 116.4074) { address, error in if let validAddress = address { print("解析得到的地址:\(validAddress)") // 可直接更新绑定的address变量或其他UI操作 // self.boundAddress = validAddress } else if let err = error { print("解析失败:\(err.localizedDescription)") } }
注意事项
- 确保Google Places SDK已正确集成,且API Key拥有Geocoding API的调用权限;
- 逆地理编码有请求配额限制,需控制调用频率;
- 如果需要更新
PlacePicker绑定的address等变量,需确保在可修改绑定的上下文(如父视图)中调用。
内容的提问来源于stack exchange,提问作者user20810748
相关产品推荐
相关产品推荐

