Adicione o CLLocationManagerDelegate
à sua herança de classe e então você pode fazer esta verificação:
Swift 1.x - versão 2.x:
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .NotDetermined, .Restricted, .Denied:
print("No access")
case .AuthorizedAlways, .AuthorizedWhenInUse:
print("Access")
}
} else {
print("Location services are not enabled")
}
Versão Swift 4.x:
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined, .restricted, .denied:
print("No access")
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
}
} else {
print("Location services are not enabled")
}
Versão Swift 5.1
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined, .restricted, .denied:
print("No access")
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
@unknown default:
break
}
} else {
print("Location services are not enabled")
}
manager.locationServicesEnabled()
vez deCLLocationManager.loationServicesEnabled()
Resolvido!authorizationStatus
está definido comonotDetermined
, em vez de apenas registrar, seria melhor solicitar ao usuário "Permitir / Não Permitir"No objetivo-c
você deve rastrear o usuário já negado ou não determinado e, em seguida, pedir permissão ou enviar o usuário ao aplicativo Setting.
-(void)askEnableLocationService { BOOL showAlertSetting = false; BOOL showInitLocation = false; if ([CLLocationManager locationServicesEnabled]) { switch ([CLLocationManager authorizationStatus]) { case kCLAuthorizationStatusDenied: showAlertSetting = true; NSLog(@"HH: kCLAuthorizationStatusDenied"); break; case kCLAuthorizationStatusRestricted: showAlertSetting = true; NSLog(@"HH: kCLAuthorizationStatusRestricted"); break; case kCLAuthorizationStatusAuthorizedAlways: showInitLocation = true; NSLog(@"HH: kCLAuthorizationStatusAuthorizedAlways"); break; case kCLAuthorizationStatusAuthorizedWhenInUse: showInitLocation = true; NSLog(@"HH: kCLAuthorizationStatusAuthorizedWhenInUse"); break; case kCLAuthorizationStatusNotDetermined: showInitLocation = true; NSLog(@"HH: kCLAuthorizationStatusNotDetermined"); break; default: break; } } else { showAlertSetting = true; NSLog(@"HH: locationServicesDisabled"); } if (showAlertSetting) { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"Please enable location service for this app in ALLOW LOCATION ACCESS: Always, Go to Setting?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Open Setting", nil]; alertView.tag = 199; [alertView show]; } if (showInitLocation) { [self initLocationManager]; } }
Implemente alertView Delegate e envie o usuário para habilitar o serviço de localização se já tiver sido negado pelo usuário.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (alertView.tag == 199) { if (buttonIndex == 1) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; } return; } }
Gerente de Localização Init
-(void)initLocationManager{ self.locationManager = [[CLLocationManager alloc] init]; if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { [self.locationManager requestAlwaysAuthorization]; } }
Observe que kCLAuthorizationStatusAuthorizedAlways e kCLAuthorizationStatusAuthorizedWhenInUse são a diferença.
fonte
SWIFT (em 24 de julho de 2018)
if CLLocationManager.locationServicesEnabled() { }
isso dirá se o usuário já selecionou uma configuração para a solicitação de permissão de localização do aplicativo
fonte
É apenas uma função de 2 linhas no Swift 4:
import CoreLocation static func isLocationPermissionGranted() -> Bool { guard CLLocationManager.locationServicesEnabled() else { return false } return [.authorizedAlways, .authorizedWhenInUse].contains(CLLocationManager.authorizationStatus()) }
fonte
Aqui está o formato recomendado pela Apple .
switch CLLocationManager.authorizationStatus() { case .notDetermined: // Request when-in-use authorization initially break case .restricted, .denied: // Disable location features break case .authorizedWhenInUse, .authorizedAlways: // Enable location features break }
Aqui está um exemplo completo.
Isso inclui um
AlertView
com um botão para levar o usuário àSettings
tela se o acesso tiver sido negado anteriormente.import CoreLocation let locationManager = CLLocationManager() class SettingsTableViewController:CLLocationManagerDelegate{ func checkUsersLocationServicesAuthorization(){ /// Check if user has authorized Total Plus to use Location Services if CLLocationManager.locationServicesEnabled() { switch CLLocationManager.authorizationStatus() { case .notDetermined: // Request when-in-use authorization initially // This is the first and the ONLY time you will be able to ask the user for permission self.locationManager.delegate = self locationManager.requestWhenInUseAuthorization() break case .restricted, .denied: // Disable location features switchAutoTaxDetection.isOn = false let alert = UIAlertController(title: "Allow Location Access", message: "MyApp needs access to your location. Turn on Location Services in your device settings.", preferredStyle: UIAlertController.Style.alert) // Button to Open Settings alert.addAction(UIAlertAction(title: "Settings", style: UIAlertAction.Style.default, handler: { action in guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return } if UIApplication.shared.canOpenURL(settingsUrl) { UIApplication.shared.open(settingsUrl, completionHandler: { (success) in print("Settings opened: \(success)") }) } })) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil)) self.present(alert, animated: true, completion: nil) break case .authorizedWhenInUse, .authorizedAlways: // Enable features that require location services here. print("Full Access") break } } } }
fonte
Para swift3.0 e superior, se forem feitas verificações frequentes para a disponibilidade de serviços de localização, crie uma classe como abaixo,
import CoreLocation open class Reachability { class func isLocationServiceEnabled() -> Bool { if CLLocationManager.locationServicesEnabled() { switch(CLLocationManager.authorizationStatus()) { case .notDetermined, .restricted, .denied: return false case .authorizedAlways, .authorizedWhenInUse: return true default: print("Something wrong with Location services") return false } } else { print("Location services are not enabled") return false } } }
e use-o assim em seu VC
if Reachability.isLocationServiceEnabled() == true { // Do what you want to do. } else { //You could show an alert like this. let alertController = UIAlertController(title: "Location Services Disabled", message: "Please enable location services for this app.", preferredStyle: .alert) let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil) alertController.addAction(OKAction) OperationQueue.main.addOperation { self.present(alertController, animated: true, completion:nil) } }
fonte
Quando você chama -startLocation, se os serviços de localização foram negados pelo usuário, o delegado do gerente de localização receberá uma chamada para -
locationManager:didFailWithError
: com okCLErrorDenied
código de erro. Isso funciona em todas as versões do iOS.fonte
Use of unresolved identifier 'kCLErrorDenied'
. Pensamentos?Em Swift 3.0
if (CLLocationManager.locationServicesEnabled()) { locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest if ((UIDevice.current.systemVersion as NSString).floatValue >= 8) { locationManager.requestWhenInUseAuthorization() } locationManager.startUpdatingLocation() } else { #if debug println("Location services are not enabled"); #endif }
fonte
Para pedir permissão para os serviços de localização que você usa:
Se o status for indeterminado no momento, um alerta será exibido, solicitando que o usuário permita o acesso. Se o acesso for negado, seu aplicativo será notificado no CLLocationManagerDelegate, da mesma forma se a permissão for negada a qualquer momento, você será atualizado aqui.
Existem dois status separados que você precisa verificar para determinar as permissões atuais.
CLLocationManager.locationServicesEnabled()
CLLocationManager.authorizationStatus() == .authorizedWhenInUse
Você pode adicionar uma extensão é uma opção útil:
extension CLLocationManager { static func authorizedToRequestLocation() -> Bool { return CLLocationManager.locationServicesEnabled() && (CLLocationManager.authorizationStatus() == .authorizedAlways || CLLocationManager.authorizationStatus() == .authorizedWhenInUse) }
}
Aqui, ele está sendo acessado quando o usuário solicitou as direções pela primeira vez:
private func requestUserLocation() { //when status is not determined this method runs to request location access locationManager.requestWhenInUseAuthorization() if CLLocationManager.authorizedToRequestLocation() { //have accuracy set to best for navigation - accuracy is not guaranteed it 'does it's best' locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation //find out current location, using this one time request location will start the location services and then stop once have the location within the desired accuracy - locationManager.requestLocation() } else { //show alert for no location permission showAlertNoLocation(locationError: .invalidPermissions) } }
Aqui está o delegado:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { if !CLLocationManager.authorizedToRequestLocation() { showAlertNoLocation(locationError: .invalidPermissions) } }
fonte