Swift开发中如何获取经纬度数值并存储到变量中?
从MKCoordinateRegion提取经纬度的实现方法
问题场景
开发SwiftUI + MapKit的用户位置获取功能时,需要从MKCoordinateRegion类型的region实例中提取纬度、经度值存储到自定义变量。现有代码运行后可在控制台打印出包含经纬度的region信息,但未掌握正确的属性取值方式。
已编写的核心代码如下:
import SwiftUI import MapKit import CoreLocationUI struct ContentView: View { @StateObject private var viewModel = ContentViewModel() @State var LongStorage : Int = 0 @State var LangStorage : Int = 0 var body: some View { ZStack(alignment: .bottom){ Map(coordinateRegion: $viewModel.region, showsUserLocation: true) .ignoresSafeArea() .tint(Color("GreenColor")) LocationButton(.currentLocation){ viewModel.requestAllowOnceLocationPermission() } .foregroundColor(.white ) .cornerRadius(10) .labelStyle(.titleAndIcon) .symbolVariant(.fill) .tint(Color("GreenColor")) .padding(.bottom, 50) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } 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.015, longitudeDelta: 0.015)) //check region value print("Region --> \(self.region)") } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print(error.localizedDescription) } }
运行后控制台输出日志如下:
Region --> MKCoordinateRegion(center: __C.CLLocationCoordinate2D(latitude: 37.33036067, longitude: -122.02845007), span: __C.MKCoordinateSpan(latitudeDelta: 0.015, longitudeDelta: 0.015))
具体实现步骤
1. 修正存储变量的类型与命名
- 经纬度是
CLLocationDegrees类型,本质为Double类型浮点数,原代码用Int类型存储会丢失小数位精度,需要先调整变量类型 - 原纬度变量名存在拼写错误(
LangStorage是语言的缩写,纬度对应Latitude的缩写),建议一并修正
// 替换ContentView中原有的两个@State存储变量 @State var longStorage: Double = 0 @State var latStorage: Double = 0
2. 通过结构体属性直接取值
不要尝试解析控制台打印的字符串获取经纬度,MKCoordinateRegion的center属性本身就是CLLocationCoordinate2D类型,直接访问其latitude、longitude属性即可拿到对应数值,这是官方SDK提供的标准取值方式,稳定性最高。
位置更新回调中支持两种等效的取值渠道:
- 直接从回调返回的最新位置对象
latestLocation.coordinate取值,不需要等待region赋值完成,效率更高 - 从赋值完成后的
self.region.center取值,和控制台打印的经纬度数值完全一致
修改后的didUpdateLocations方法代码如下:
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.015, longitudeDelta: 0.015)) // 提取经纬度 let currentLat = latestLocation.coordinate.latitude let currentLong = latestLocation.coordinate.longitude // 如果要从region取值,替换成下面两行即可 // let currentLat = self.region.center.latitude // let currentLong = self.region.center.longitude // 赋值给存储变量即可使用,控制台可打印验证 print("提取到的纬度:\(currentLat),经度:\(currentLong)") } }
3. (可选)在ViewModel层持有经纬度
如果需要全局使用经纬度,不需要在View层单独定义存储变量,直接在ContentViewModel中添加两个被@Published修饰的Double类型属性,拿到值后直接赋值,View层可以通过viewModel.latitude、viewModel.longitude直接访问,状态会自动同步。
内容的提问来源于stack exchange,提问作者Rakha Fatih
相关产品推荐
相关产品推荐

