Vérifiez si les services de localisation sont activés

87

J'ai fait des recherches sur CoreLocation. Récemment, j'ai rencontré un problème qui a été traité ailleurs, mais en Objective C, et pour iOS 8.

Je me sens un peu idiot de demander cela, mais comment pouvez-vous vérifier si les services de localisation sont activés en utilisant Swift, sur iOS 9?

Sur iOS 7 (et peut-être 8?), Vous pouvez utiliser locationServicesEnabled(), mais cela ne semble pas fonctionner lors de la compilation pour iOS 9.

Alors, comment pourrais-je accomplir cela?

Merci!

Brendan Chang
la source

Réponses:

244

Ajoutez le CLLocationManagerDelegateà votre héritage de classe, puis vous pouvez effectuer cette vérification:

Version Swift 1.x - 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")
}

Version 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")
}

Version de 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")
}
Rashwan L
la source
8
Ouaip! Merci! Mon problème était que j'essayais d'appeler locatoinServicesEnabled sur mon manager, c'est-à-dire manager.locationServicesEnabled() plutôt que CLLocationManager.loationServicesEnabled() résolu!
Brendan Chang
2
Je comprends que votre code n'est qu'un exemple, mais il est légèrement trompeur ... Je pense que c'est mieux quand authorizationStatusest défini sur notDeterminedalors au lieu de simplement se connecter, il serait préférable d'inviter l'utilisateur 'Autoriser / Ne pas autoriser'
Honey
@Honey, bien sûr, vous pouvez bien sûr l'utiliser comme vous préférez et comme vous l'avez dit, le code n'est qu'un exemple pour montrer comment il pourrait être utilisé.
Rashwan L
13

Dans l'objectif-c

vous devez suivre l'utilisateur déjà refusé ou non déterminé, puis demander l'autorisation ou envoyer l'utilisateur à l'application de configuration.

-(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];
   }

}

Implémentez alertView Delegate puis envoyez l'utilisateur pour activer le service de localisation s'il est déjà refusé par l'utilisateur.

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

   if (alertView.tag == 199) {
       if (buttonIndex == 1) {
           [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
       }
       return;
   }
}

Gestionnaire d'emplacement init

-(void)initLocationManager{
   self.locationManager = [[CLLocationManager alloc] init];
   if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
       [self.locationManager requestAlwaysAuthorization];
   }
}

Veuillez noter que kCLAuthorizationStatusAuthorizedAlways et kCLAuthorizationStatusAuthorizedWhenInUse font la différence.

Marosdee Uma
la source
Merci pour cette version objective-c, même si la question initiale portait sur Swift. Conseils supplémentaires: appelez requestWhenInUseAuthorization si le statut n'est pas déterminé, définissez l'entrée plist appropriée pour la description de l'utilisation (éventuellement localisée), et éventuellement implémentez didChangeAuthorizationStatus
Giorgio Barchiesi
9

SWIFT (au 24 juillet 2018)

if CLLocationManager.locationServicesEnabled() {

}

cela vous dira si l'utilisateur a déjà sélectionné un paramètre pour la demande d'autorisation de localisation de l'application

BennyTheNerd
la source
8

Ce n'est qu'une fonction à 2 lignes dans Swift 4:

import CoreLocation

static func isLocationPermissionGranted() -> Bool
{
    guard CLLocationManager.locationServicesEnabled() else { return false }
    return [.authorizedAlways, .authorizedWhenInUse].contains(CLLocationManager.authorizationStatus())
}
Suat KARAKUSOGLU
la source
6

Voici le format recommandé par 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
      }

Voici un exemple complet.

Cela inclut AlertViewun bouton avec un bouton pour amener l'utilisateur à l' Settingsécran s'il a précédemment refusé l'accès.

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
            }
        }
    }
}
fs_tigre
la source
5

Pour swift3.0 et supérieur, si des vérifications fréquentes sont effectuées pour la disponibilité des services de localisation, créez une classe comme ci-dessous,

    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
              }
            }
         }

puis utilisez-le comme ça dans votre 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)
        }
    }
Sri Hari YS
la source
3

Lorsque vous appelez -startLocation, si les services de localisation ont été refusés par l'utilisateur, le délégué du gestionnaire d'emplacement recevra un appel à - locationManager:didFailWithError: avec le kCLErrorDeniedcode d'erreur. Cela fonctionne à la fois dans toutes les versions d'iOS.

Shaheen Sharifian
la source
Merci. Malheureusement, quand j'ai essayé, il montre: Use of unresolved identifier 'kCLErrorDenied'. Pensées?
Brendan Chang le
1

Dans 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
            }
Amul4608
la source
1

Pour demander l'autorisation des services de localisation que vous utilisez:

yourSharedLocationManager.requestWhenInUseAuthorization()

Si l'état est actuellement indéterminé, une alerte s'affichera, invitant l'utilisateur à autoriser l'accès. Si l'accès est refusé, votre application sera notifiée dans CLLocationManagerDelegate, de même si l'autorisation est refusée à tout moment, vous serez mis à jour ici.

Vous devez vérifier deux états distincts pour déterminer les autorisations actuelles.

  • Si l'utilisateur a activé ou non les services de localisation générale

CLLocationManager.locationServicesEnabled()

  • Si l'utilisateur a accordé l'autorisation appropriée pour votre application.

CLLocationManager.authorizationStatus() == .authorizedWhenInUse

Vous pouvez ajouter une extension est une option pratique:

extension CLLocationManager {
static func authorizedToRequestLocation() -> Bool {
    return CLLocationManager.locationServicesEnabled() &&
        (CLLocationManager.authorizationStatus() == .authorizedAlways || CLLocationManager.authorizationStatus() == .authorizedWhenInUse)
}

}

Ici, il est accessible lorsque l'utilisateur a demandé pour la première fois un itinéraire:

 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)
    }
}

Voici le délégué:

 func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

    if !CLLocationManager.authorizedToRequestLocation() {
        showAlertNoLocation(locationError: .invalidPermissions)
    }
}
Jess
la source