Controlla se i servizi di localizzazione sono abilitati


88

Ho fatto delle ricerche su CoreLocation. Recentemente, ho riscontrato un problema che è stato trattato altrove, ma in Objective C e per iOS 8.

Mi sento un po 'sciocco chiederlo, ma come puoi verificare se i servizi di localizzazione sono abilitati utilizzando Swift, su iOS 9?

Su iOS 7 (e forse 8?) Potresti usare locationServicesEnabled(), ma sembra che non funzioni durante la compilazione per iOS 9.

Quindi come potrei farlo?

Grazie!

Risposte:


247

Aggiungi CLLocationManagerDelegatealla tua eredità di classe e poi puoi fare questo controllo:

Swift 1.x - 2.x version:

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

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

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

8
Sì! Grazie! Il mio problema era che stavo cercando di chiamare locatoinServicesEnabled sul mio manager, cioè manager.locationServicesEnabled() piuttosto che CLLocationManager.loationServicesEnabled() Risolto!
Brendan Chang

2
Ho capito che il tuo codice è solo un esempio, ma è leggermente fuorviante ... Penso che sia meglio quando authorizationStatusè impostato su, notDeterminedinvece di registrarsi sarebbe meglio chiedere all'utente "Consenti / Non consentire"
Honey

@ Tesoro, certo che potresti ovviamente usarlo come preferisci e come hai detto il codice è solo un esempio per mostrare come potrebbe essere usato.
Rashwan L

13

Nell'obiettivo-c

dovresti monitorare l'utente già negato o non determinato, quindi chiedere l'autorizzazione o inviare l'utente all'app Impostazioni.

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

}

Implementare alertView Delegate, quindi inviare l'utente per abilitare il servizio di localizzazione se già negato dall'utente.

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

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

Init Location Manager

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

Tieni presente che kCLAuthorizationStatusAuthorizedAlways e kCLAuthorizationStatusAuthorizedWhenInUse fanno la differenza.


Grazie per questa versione dell'obiettivo c, anche se la domanda originale riguardava la rapidità. Ulteriori suggerimenti: chiamare requestWhenInUseAuthorization se lo stato non è determinato, impostare la relativa voce plist per la descrizione dell'utilizzo (possibilmente localizzata), ed eventualmente implementare didChangeAuthorizationStatus
Giorgio Barchiesi

9

SWIFT (A partire dal 24 luglio 2018)

if CLLocationManager.locationServicesEnabled() {

}

questo ti dirà se l'utente ha già selezionato un'impostazione per la richiesta di autorizzazione alla posizione dell'app


8

È solo una funzione di 2 righe in Swift 4:

import CoreLocation

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

6

Ecco il formato consigliato da 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
      }

Ecco un esempio completo.

Questo include un AlertViewpulsante per portare l'utente sullo Settingsschermo se in precedenza gli è stato negato l'accesso.

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

5

Per swift3.0 e versioni successive, se vengono effettuati controlli frequenti per la disponibilità dei servizi di localizzazione, creare una classe come di seguito,

    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 poi usalo in questo modo nel tuo 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)
        }
    }

3

Quando si chiama -startLocation, se i servizi di posizione sono stati negati dall'utente, il delegato del gestore di posizione riceverà una chiamata a - locationManager:didFailWithError: con il kCLErrorDeniedcodice di errore. Funziona sia in tutte le versioni di iOS.


Grazie. Purtroppo, quando ho provato che, si vede: Use of unresolved identifier 'kCLErrorDenied'. Pensieri?
Brendan Chang

1

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

1

Per chiedere l'autorizzazione per i servizi di localizzazione che utilizzi:

yourSharedLocationManager.requestWhenInUseAuthorization()

Se lo stato è attualmente indeterminato, verrà visualizzato un avviso che richiede all'utente di consentire l'accesso. Se l'accesso viene negato, la tua app verrà notificata in CLLocationManagerDelegate, allo stesso modo se l'autorizzazione viene negata in qualsiasi momento sarai aggiornato qui.

Ci sono due stati separati che devi controllare per determinare le autorizzazioni correnti.

  • Se l'utente ha i servizi di localizzazione generali abilitati o meno

CLLocationManager.locationServicesEnabled()

  • Se l'utente ha concesso l'autorizzazione corretta per la tua app ..

CLLocationManager.authorizationStatus() == .authorizedWhenInUse

Potresti aggiungere un'estensione è un'opzione utile:

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

}

Qui si accede quando l'utente ha prima richiesto le indicazioni:

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

Ecco il delegato:

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

    if !CLLocationManager.authorizedToRequestLocation() {
        showAlertNoLocation(locationError: .invalidPermissions)
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.