LocationManager不返回坐标 SwiftUI调用时获取经纬度为0,0问题排查
问题根因
你遇到的是典型的异步定位时序问题:
- LocationManager从申请权限、到获取GPS定位结果是后台异步操作,有几十毫秒到数秒的耗时,不会阻塞主线程的初始化流程
- 你在
DownloadWeatherLocation的init方法里刚实例化locationManager就立刻读取lastLocation,此时定位请求还未完成,lastLocation为nil,自然触发??后的默认值0
你看到控制台能打印正常经纬度,是因为日志是在定位完成的回调里输出的,时间远晚于init里调用天气接口的时机,时序不匹配导致参数错误。
解决方法
核心逻辑是监听定位结果的更新,拿到有效坐标后再调用天气接口,不要在init里直接触发接口请求。
假设你使用的LocationManager是参考帖子实现的ObservableObject,lastLocation为@Published修饰的属性,修改代码如下:
class DownloadWeatherLocation: ObservableObject { @Published var weatherlocationdata: [WeatherLocationDecoder] = [] let locationManager = LocationManager() @AppStorage("userWID") var userWID = 0 @AppStorage("userLocationCity") var userLocationCity = "" var weatherDataCancellabes = Set<AnyCancellable>() init() { print("WeatherLocation: loading init") // 监听定位结果更新 locationManager.$lastLocation // 过滤空的无效定位结果 .compactMap { $0 } // 只取第一次有效定位即可,避免重复调用接口 .first() // 拿到坐标后再调用天气接口 .sink { [weak self] location in guard let self = self else { return } let userLatitude = "\(location.coordinate.latitude)" let userLongitude = "\(location.coordinate.longitude)" self.getWeatherLocation(weatherlocationUrl: "https://www.metaweather.com/api/location/search/?lattlong=\(userLatitude),\(userLongitude)") } .store(in: &weatherDataCancellabes) } // getWeatherLocation原有实现保持不变即可 }
如果你的LocationManager没有用@Published修饰lastLocation,先修改LocationManager的实现,给lastLocation加上@Published包装,才能通过Combine监听属性变化。
额外排查点
如果修改后仍然有问题,按以下步骤验证:
- 确认info.plist里已经添加了对应定位权限的描述字段(NSLocationWhenInUseUsageDescription等),用户已经授予了定位权限
- 确认
LocationManager内部已经调用了startUpdatingLocation()方法启动定位 - 可以在上面
sink的回调里加打印,确认是否正常收到了定位结果回调
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

