You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CLLocationManager无法获取用户位置的技术求助

无法通过CLLocationManager获取用户位置的问题

错误信息

运行应用时控制台输出:

[WeatherDataService] Response did not contain requested dataset: .appLocationConfig. Returning default value: AppLocationConfig(reportAnIssue: ReportIssueLocationConfig(position: beforeFooter, minDaysSinceInteraction: 0), expireTime: 2023-01-23 07:30:06 +0000

相关代码

LocationManager类及扩展

class LocationManager: NSObject, ObservableObject {
    
    @Published var currentLocation: CLLocation?
    private let locationManager = CLLocationManager()
    
    override init() {
        super.init()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = kCLDistanceFilterNone
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
        locationManager.delegate = self
    }
    
}

extension LocationManager: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        guard let location = locations.last, currentLocation == nil else { return }
        
        DispatchQueue.main.async {
            self.currentLocation = location
        }
    }
}

视图代码(VStack部分)

VStack{
    if let weather {
        VStack{
            HStack{
                Text("Singapore")
                    .padding()
                    .font(.largeTitle)
            VStack {
                Text("Condition: \(weather.currentWeather.condition.rawValue)")
                    .font(.title2)
                Text("Temperature: \(weather.currentWeather.temperature.formatted())")
                    .font(.title2)
                Text("Feels like: \(weather.currentWeather.apparentTemperature.formatted())")
                    .font(.title2)
//              Text("Min: \() Max: \()")
//                  .font(.title)
            }
        }
        Text("Today, \(weather.currentWeather.date.formatted())")
                        .font(.subheadline)
    }
                
    ScrollView(.vertical){
        VStack{
            HourlyForcastView(hourWeatherList: hourlyWeatherData, hourlyWeatherData: hourlyWeatherData)
            TenDayForcastView(dayWeatherList: weather.dailyForecast.forecast)
                        
            HStack{
                // Humidity
                VStack{
                    Image(systemName: "humidity")
                        .font(.system(size: 65))
                        .foregroundColor(.yellow)
                    let humidity = (weather.currentWeather.humidity * 100)
                    Text("HUMIDITY")
                        .font(.headline)
                        .foregroundColor(.white)
                    Text("\(humidity.formatted())%")
                        .foregroundColor(.white)
                }
                    .frame(width: 155)
                    .padding()
                    .background(content: {Color.blue})
                    .clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
                            
                // Pressure
                VStack{
                    HStack{
                        Image(systemName: "arrow.down")
                            .resizable()
                            .frame(width: 40, height: 60)
                            .foregroundColor(.yellow)
                        Image(systemName: "arrow.down")
                            .resizable()
                            .frame(width: 40, height: 60)
                            .foregroundColor(.yellow)
                        Image(systemName: "arrow.down")
                            .resizable()
                            .frame(width: 40, height: 60)
                            .foregroundColor(.yellow)
                    }
                    let pressure = (weather.currentWeather.pressure)
                        Text("PRESSURE")
                            .font(.headline)
                            .foregroundColor(.white)
                        Text("\(pressure.formatted())")
                            .foregroundColor(.white)
                }
                    .frame(width: 155)
                    .padding()
                    .background(content: {Color.blue})
                    .clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
                        }
                        
                HStack{
                    // Dew Point
                    VStack{
                        HStack{
                            Image(systemName: "drop")
                                .font(.system(size: 56.5))
                                .foregroundColor(.yellow)
                            Image(systemName: "drop")
                                .font(.system(size: 56.5))
                                .foregroundColor(.yellow)
                        }
                        let dewPoint = (weather.currentWeather.dewPoint)
                        Text("DEW POINT")
                            .font(.headline)
                            .foregroundColor(.white)
                        Text("\(dewPoint.formatted())")
                            .foregroundColor(.white)
                }
                    .frame(width: 155)
                    .padding()
                    .background(content: {Color.blue})
                    .clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
                            
                // UV Index
                VStack{
                    Image(systemName: "sun.max")
                        .font(.system(size: 53))
                        .foregroundColor(.yellow)
                    let uvIndex = (weather.currentWeather.uvIndex)
                    Text("UV INDEX")
                        .font(.headline)
                        .foregroundColor(.white)
                    Text("\(uvIndex.value) - \(uvIndex.category.rawValue)")
                        .foregroundColor(.white)
                }
                            .frame(width: 155)
                            .padding()
                            .background(content: {Color.blue})
                            .clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
                            
                        }
                        HStack{
                            // Wind Speed
                            VStack{
                                Image(systemName: "wind")
                                    .font(.system(size: 53))
                                    .foregroundColor(.yellow)
                                let windSpeed = (weather.currentWeather.wind)
                                Text("WIND SPEED")
                                    .font(.headline)
                                    .foregroundColor(.white)
                                Text("\(windSpeed.speed.formatted())")
                                    .foregroundColor(.white)
                            }
                            .frame(width: 155)
                            .padding()
                            .background(content: {Color.blue})
                            .clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
                            
                            // Wind Direction
                            VStack{
                                Image(systemName: "wind")
                                    .font(.system(size: 53))
                                    .foregroundColor(.yellow)
                                let windSpeed = (weather.currentWeather.wind)
                                Text("WIND DIRECTION")
                                    .font(.headline)
                                    .foregroundColor(.white)
                                Text("\(windSpeed.compassDirection.rawValue)")
                                    .foregroundColor(.white)
                            }
                            .frame(width: 155)
                            .padding()
                            .background(content: {Color.blue})
                            .clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
                        }
                        HStack{
                            // Visibility
                            VStack{
                                Image(systemName: "mountain.2")
                                    .font(.system(size: 53))
                                    .foregroundColor(.yellow)
                                let visibility = (weather.currentWeather.visibility)
                                Text("VISIBILITY")
                                    .font(.headline)
                                    .foregroundColor(.white)
                                Text("\(visibility.formatted())")
                                    .foregroundColor(.white)
                            }
                            .frame(width: 155)
                            .padding()
                            .background(content: {Color.blue})
                            .clipShape(RoundedRectangle(cornerRadius: 10.0, style: .continuous))
                        }
                    }
                }
            }
        }

Task代码

} // This is where the VStack ends.
    .padding()
    .task(id: locationManager.currentLocation) {
        do {
//          if let location = locationManager.currentLocation {
                let location = CLLocation(latitude: 1.30437, longitude: 103.82458)
                self.weather =  try await weatherService.weather(for: location)
//          }
        } catch {
            print(error)
          }
           
        }

当前临时方案

目前通过硬编码新加坡的坐标(CLLocation(latitude: 1.30437, longitude: 103.82458))来获取天气数据,但无法正常获取用户的实际位置。


解决方案

1. 配置Info.plist权限描述

使用requestAlwaysAuthorization()需要在Info.plist中添加以下权限说明:

  • 添加NSLocationAlwaysAndWhenInUseUsageDescription(字符串类型),填写权限用途,比如“需要获取您的位置以提供精准天气服务”
  • 添加NSLocationWhenInUseUsageDescription(字符串类型),填写相同或对应用途说明

如果仅需前台获取位置,可以改用requestWhenInUseAuthorization(),但仍需配置NSLocationWhenInUseUsageDescription。

2. 完善LocationManager代理方法

添加权限状态监听和错误处理的代理方法到LocationManager扩展:

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    switch status {
    case .notDetermined:
        manager.requestAlwaysAuthorization()
    case .authorizedAlways, .authorizedWhenInUse:
        manager.startUpdatingLocation()
    case .denied, .restricted:
        print("位置权限被拒绝,请前往设置开启")
    @unknown default:
        break
    }
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print("获取位置失败:\(error.localizedDescription)")
}

3. 调整初始化逻辑

将启动位置更新的代码移到权限授权成功后执行,修改LocationManager的init方法:

override init() {
    super.init()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = kCLDistanceFilterNone
    locationManager.delegate = self
    locationManager.requestAlwaysAuthorization()
}

4. 修复Task逻辑

取消注释位置判断代码,确保仅在获取到用户位置后请求天气数据:

.task(id: locationManager.currentLocation) {
    do {
        if let location = locationManager.currentLocation {
            self.weather = try await weatherService.weather(for: location)
        }
    } catch {
        print(error)
    }
}

关于.appLocationConfig错误

该错误来自WeatherDataService,与CLLocationManager无关,是天气服务返回数据缺少指定配置项,服务内部已返回默认值,不会影响位置获取功能,可忽略。


内容的提问来源于stack exchange,提问作者Aadish123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 02:30:43