Swift调用CLLocationManager.locationServicesEnabled()触发主线程卡顿警告问题
解决CLLocationManager.locationServicesEnabled()主线程警告问题
根据苹果的提示,直接在主线程调用CLLocationManager.locationServicesEnabled()可能阻塞UI,正确的做法是先初始化定位管理器并等待授权状态回调,再根据授权情况判断是否需要检查系统定位服务是否开启。
重构后的代码
import Foundation import MapKit final class MapViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { var locationManager: CLLocationManager? @Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 37.773972, longitude: -122.431297), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)) @Published var accurateUserLocationRetrieved: Bool = false // 初始化时直接创建定位管理器并设置代理 override init() { super.init() setupLocationManager() } private func setupLocationManager() { locationManager = CLLocationManager() locationManager?.desiredAccuracy = kCLLocationAccuracyBest locationManager?.delegate = self // 直接触发授权状态检查(会自动调用locationManagerDidChangeAuthorization) locationManager?.requestWhenInUseAuthorization() } private func checkLocationAuthorization() { guard let locationManager = locationManager else { return } switch locationManager.authorizationStatus { case .notDetermined: locationManager.requestWhenInUseAuthorization() case .restricted, .denied: // 只有当授权被拒绝/限制时,再检查系统定位服务是否开启 if !CLLocationManager.locationServicesEnabled() { print("Show alert letting them know it is off and tell them to turn on.") } else { if locationManager.authorizationStatus == .restricted { print("Your location is restricted") } else { print("You have denied location permission") } } case .authorizedAlways, .authorizedWhenInUse: if let userLocation = locationManager.location { region = MKCoordinateRegion(center: userLocation.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)) accurateUserLocationRetrieved = true } @unknown default: break } } func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { checkLocationAuthorization() } }
关键修改点
- 移除提前检查locationServicesEnabled()的逻辑:不再在初始化或单独方法里先判断系统服务,而是先创建
CLLocationManager并设置代理,触发授权请求。 - 延迟检查系统服务:仅当授权状态为
denied或restricted时,才调用locationServicesEnabled(),这时候可以区分是用户拒绝了权限,还是系统级的定位服务被关闭。 - 安全获取用户位置:使用可选绑定
if let userLocation = locationManager.location避免强制解包崩溃。
这样既遵循了苹果的建议,消除了主线程警告,同时也能正确处理各种定位权限和系统服务状态。
内容的提问来源于stack exchange,提问作者Karam Eid
相关产品推荐
相关产品推荐

