如何判断已向用户请求过locationManager.requestAlwaysAuthorization()?
Alright, let's tackle your two iOS location permission questions one by one—this is a super common scenario, so I’ve got you covered.
iOS doesn’t provide a direct API to tell you if you’ve called locationManager.requestAlwaysAuthorization() before, but we can work around this by tracking the request ourselves using UserDefaults. Here’s how:
- Track the request state: When you first initiate the Always authorization request, save a boolean flag to
UserDefaultsto mark that the request has been made. - Check the flag later: Whenever you need to verify if the request was sent, just look up that flag.
Example code:
// Define a key to store our request state private let hasRequestedAlwaysAuthKey = "HasRequestedAlwaysLocationAuthorization" // Call this when you want to request Always auth (if not already done) func requestAlwaysAuthorizationIfNeeded() { let locationManager = CLLocationManager() let currentStatus = locationManager.authorizationStatus guard currentStatus == .notDetermined else { return } // Mark that we've initiated the request UserDefaults.standard.set(true, forKey: hasRequestedAlwaysAuthKey) locationManager.requestAlwaysAuthorization() } // Use this to check if Always auth was ever requested func hasRequestedAlwaysAuthorization() -> Bool { return UserDefaults.standard.bool(forKey: hasRequestedAlwaysAuthKey) }
If the user is already on .AuthorizedWhenInUse and previously declined (or opted for WhenInUse instead of) Always authorization, iOS won’t show the prompt again when you call requestAlwaysAuthorization()—this is intentional behavior, since the user has already made a choice about Always access. Here’s your solution:
- Detect the scenario: When the current status is
.authorizedWhenInUseand yourUserDefaultsflag shows you’ve already requested Always auth, skip callingrequestAlwaysAuthorization()entirely. - Guide the user to Settings: Instead of trying to re-trigger the prompt (which won’t work), show a clear, user-friendly alert explaining why you need Always access, then provide a button to jump directly to your app’s Settings page where they can update the permission.
- Listen for permission changes: Use the location manager delegate to detect when the user returns from Settings, so you can re-check the authorization status and proceed accordingly.
Example implementation:
func handleLocationAuthorizationStatus(_ status: CLAuthorizationStatus) { switch status { case .authorizedWhenInUse: if hasRequestedAlwaysAuthorization() { // User already chose against Always auth—send them to Settings showSettingsPermissionPrompt() } else { // Haven't requested Always yet—initiate the request let locationManager = CLLocationManager() UserDefaults.standard.set(true, forKey: hasRequestedAlwaysAuthKey) locationManager.requestAlwaysAuthorization() } case .notDetermined: // First-time request—go for Always auth let locationManager = CLLocationManager() UserDefaults.standard.set(true, forKey: hasRequestedAlwaysAuthKey) locationManager.requestAlwaysAuthorization() case .authorizedAlways: // Permission is good—start your location logic startLocationTracking() case .denied, .restricted: // Permission is blocked—guide to Settings showSettingsPermissionPrompt() @unknown default: break } } func showSettingsPermissionPrompt() { let alert = UIAlertController( title: "Need Always Location Access", message: "To provide [your feature/service name], we need permission to access your location even when the app is closed. Please update this in Settings.", preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in guard let settingsURL = URL(string: UIApplication.openSettingsURLString) else { return } if UIApplication.shared.canOpenURL(settingsURL) { UIApplication.shared.open(settingsURL) } }) present(alert, animated: true) } // Delegate method to listen for permission changes after user returns from Settings extension YourViewController: CLLocationManagerDelegate { func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { handleLocationAuthorizationStatus(manager.authorizationStatus) } }
A quick note: Make sure your Info.plist includes both NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription keys with clear explanations—iOS requires these to show any location permission prompts.
内容的提问来源于stack exchange,提问作者Pablo Blanco

