Xcode 模拟器位置授权问题:拒绝授权后,系统设置更改无效,授权状态始终为 notDetermined?

我在模拟器上遇到一个关于位置授权的奇怪问题,希望大家能帮我分析一下。
问题描述:

  1. 我的 App 在模拟器上首次运行时,会请求位置权限。
  2. 我选择“拒绝”授权。
  3. 然后,我通过模拟器的“设置” -> “隐私与安全性” -> “位置服务”中,开启了位置权限。
  4. 但是,当我返回 App 时,CLLocationManager.authorizationStatus 始终返回 .notDetermined,并且无法再次弹出授权请求弹窗。
  5. 即使我多次重置模拟器设置,问题依然存在。
import CoreLocation

@Observable
final class LocationManager: NSObject, CLLocationManagerDelegate {
   
   var locationManager = CLLocationManager()
   var currentLocation: CLLocationCoordinate2D?
   
   override init() {
      super.init()
      locationManager.delegate = self
   }
   
   // 位置权限发生变化时被调用
   func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
      let status = manager.authorizationStatus
      print("Authorize Status: \(status)")
      
      switch status {
      case .authorizedWhenInUse, .authorizedAlways:
         locationManager.startUpdatingLocation() // 开始更新位置
      case .denied, .restricted:
         stopLocation() // 停止位置更新
      case .notDetermined:
         // 如果用户未做出选择,尝试请求权限
         locationManager.requestWhenInUseAuthorization() // 请求位置权限
         print("Location permission not determined.")
      @unknown default:
         break
      }
   }
   
   // 单次请求位置
   func requestLocation() {
      let status = locationManager.authorizationStatus
      if status == .authorizedWhenInUse || status == .authorizedAlways {
         locationManager.requestLocation()
      } else {
         locationManager.requestWhenInUseAuthorization()
      }
   }
   
   // 位置更新时被调用
   func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
      guard let newLocation = locations.first else { return }
      currentLocation = newLocation.coordinate
      print("Updated location: \(newLocation.coordinate)")
   }
   
   // 当位置更新失败时调用
   func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
      print("Location update failed with error: \(error.localizedDescription)")
      currentLocation = nil
      // 在实际应用中,你可能需要通知调用者位置更新失败
   }
   
   // 停止位置更新
   func stopLocation() {
      locationManager.stopUpdatingLocation()
      print("Stopped updating location")
   }
}

image.png

阅读 732
avatarAI BotBETA

问题原因分析:

  1. 代理时序问题
    init() 中设置 locationManager.delegate = self 可能导致代理未正确绑定(某些情况下 Swift 初始化顺序不稳定)。建议将 delegate 的设置放在 CLLocationManager 的懒加载初始化中。
  2. 状态缓存问题
    模拟器可能存在位置权限状态缓存。当通过系统设置手动修改权限后,应用需要重启或主动重新触发权限检查。
  3. 权限请求逻辑冲突
    .notDetermined 分支中再次调用 requestWhenInUseAuthorization() 可能导致循环逻辑,特别是当用户已经通过系统设置修改权限时。

解决方案代码调整:

// 修改初始化方式为懒加载
lazy var locationManager: CLLocationManager = {
    let manager = CLLocationManager()
    manager.delegate = self  // 确保代理在正确时机设置
    return manager
}()

// 修改权限检查逻辑
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
    let status = manager.authorizationStatus
    print("Current Status: \(status.rawValue)")  // 添加详细状态输出
    
    switch status {
    case .authorizedWhenInUse, .authorizedAlways:
        manager.startUpdatingLocation()
    case .denied, .restricted:
        // 当权限被拒绝时,不再重复请求
        stopLocation()
        // 可以在此提示用户去设置中开启权限
    case .notDetermined:
        // 仅当从未请求过时才触发弹窗
        manager.requestWhenInUseAuthorization()
    @unknown default:
        break
    }
}

补充操作步骤:

  1. 清除模拟器缓存
    在 Xcode 中执行以下操作:

    Product -> Clean Build Folder
    Simulator -> Device -> Erase All Content and Settings
  2. 添加权限描述字段
    确保 Info.plist 包含:

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>需要位置权限来提供相关服务</string>
  3. 强制刷新权限状态
    在应用启动时添加:

    func applicationDidBecomeActive(_ application: UIApplication) {
        let status = locationManager.authorizationStatus
        if status != .notDetermined {
            locationManagerDidChangeAuthorization(locationManager)
        }
    }

验证方法:

  1. 首次启动应用选择 "拒绝"
  2. 完全终止应用进程(双击 Home 键上滑关闭)
  3. 通过系统设置开启位置权限
  4. 冷启动应用(不要通过 Xcode 重新运行)

此时应看到授权状态变为 .authorizedWhenInUse,且能正常获取位置。

1 个回答
  1. 重新设置 locationManager对象,设置代理后重新请求权限试试 ,有真机的话真机也可以试试
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进