Apple Watch应用调用requestWhenInUseAuthorization无权限弹窗问题排查
更新
我创建了一个小型Xcode项目用于复现该问题。
我正在开发一款Apple Watch应用,需要获取用户位置信息。问题在于,当我请求定位权限时,权限请求弹窗并未弹出,尽管authorizationStatus状态为.notDetermined。
我的代码如下:
WorkoutManager.swift
import Foundation import CoreLocation class WorkoutManager: NSObject, ObservableObject { let locationManager = CLLocationManager() func requestLocationAuthorization() { print("prepare to request location permission") locationManager.requestWhenInUseAuthorization() if CLLocationManager.locationServicesEnabled() { print("it is enabled") switch locationManager.authorizationStatus { case .notDetermined: print("not determined") case .restricted: print("restricted") case .denied: print("denied") case .authorizedAlways, .authorizedWhenInUse: print("Access") } } else { print("it is not enabled") } } }
RunnerApp.swift
import SwiftUI @main struct RunnerApp: App { @StateObject var workoutManager = WorkoutManager() @SceneBuilder var body: some Scene { WindowGroup { NavigationView { ContentView() } .environmentObject(workoutManager) } } }
ContentView.swift
import SwiftUI struct ContentView: View { @EnvironmentObject var workoutManager: WorkoutManager var body: some View { ScrollView { Text("Hello World") } .navigationBarTitleDisplayMode(.inline) .navigationTitle("Test") .onAppear() { print("on appear - content view") workoutManager.requestLocationAuthorization() } } }
输出日志:
on appear - content view prepare to request location permission it is enabled not determined
我想知道,既然权限状态仍为.notDetermined,为何requestWhenInUseAuthorization()没有任何效果?
问题原因及解决方案:
缺少Info.plist权限描述
Apple Watch应用必须在Info.plist中添加对应的定位权限描述键,否则系统不会弹出权限请求弹窗。需要添加以下至少一个键:NSLocationWhenInUseUsageDescription:填写应用在使用时需要定位的原因NSLocationAlwaysAndWhenInUseUsageDescription:若需始终获取定位权限则添加此键
可直接在Xcode的"Info"标签页中添加对应条目,填写清晰的权限说明文本。
未设置CLLocationManager代理
CLLocationManager需要设置代理才能接收权限状态变化的回调,同时WorkoutManager需遵守CLLocationManagerDelegate协议。修改代码如下:class WorkoutManager: NSObject, ObservableObject, CLLocationManagerDelegate { let locationManager = CLLocationManager() override init() { super.init() locationManager.delegate = self // 设置代理 } func requestLocationAuthorization() { print("prepare to request location permission") if CLLocationManager.authorizationStatus() == .notDetermined { locationManager.requestWhenInUseAuthorization() } } // 监听权限状态变化的代理方法 func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { print("Authorization status changed to: \(manager.authorizationStatus)") switch manager.authorizationStatus { case .notDetermined: print("not determined") case .restricted: print("restricted") case .denied: print("denied") case .authorizedAlways, .authorizedWhenInUse: print("Access granted") } } }异步请求的即时状态检查无效
调用requestWhenInUseAuthorization()后立刻检查权限状态是无效的,因为权限请求是异步操作。必须通过CLLocationManagerDelegate的locationManagerDidChangeAuthorization方法监听状态变化。Apple Watch定位权限特殊性
确保Apple Watch模拟器或设备的定位服务已开启;若为配对iPhone的Watch设备,需确认iPhone上的定位权限设置未限制Watch应用的权限。
内容的提问来源于stack exchange,提问作者gie3d

