Проверка разрешения службы определения местоположения на iOS

Как я могу проверить, включена ли служба определения местоположения для моего приложения?

У меня есть 2 раскадровки, и я хочу проверить местоположение службы. Если для моего приложения включена служба определения местоположения, я хочу запустить раскадровку карты с указанием местоположения. В противном случае я хочу запустить еще одну раскадровку. Как я могу сделать программно?

7 ответов

Решение

Это правильно.

if ([CLLocationManager locationServicesEnabled]){

    NSLog(@"Location Services Enabled");

    if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
        alert = [[UIAlertView alloc] initWithTitle:@"App Permission Denied"     
                                           message:@"To re-enable, please go to Settings and turn on Location Service for this app." 
                                          delegate:nil 
                                 cancelButtonTitle:@"OK" 
                                 otherButtonTitles:nil];
        [alert show];
    }
}

Протестировано на iOS 9.2

Для получения обновлений местоположения мы всегда должны проверять

  • Службы определения местоположения включены на устройстве iOS пользователя и
  • Услуги определения местоположения включены для конкретного приложения

и запуск пользователя на экране правильных настроек, чтобы включить

Запустите страницу настроек местоположения устройства iOS

Шаг 1 Перейдите в Настройки проекта -> Информация -> Типы URL -> Добавить новые схемы URL

введите описание изображения здесь

Шаг 2 Используйте приведенный ниже код для запуска страницы настроек местоположения прямого телефона: (Примечание. Схема URL-адреса отличается в iOS 10+, мы проверяем версию, как указано здесь)

 #define SYSTEM_VERSION_LESS_THAN(v)  ([[[UIDevice 
 currentDevice] systemVersion] compare:v options:NSNumericSearch] == 
 NSOrderedAscending)

 //Usage
NSString* url = SYSTEM_VERSION_LESS_THAN(@"10.0") ? @"prefs:root=LOCATION_SERVICES" : @"App-Prefs:root=Privacy&path=LOCATION";
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];

введите описание изображения здесь

Запустите страницу настроек местоположения приложения

Используйте приведенный ниже код для запуска страницы настроек местоположения приложения

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

введите описание изображения здесь

Вот полный пример кода:

#define SYSTEM_VERSION_LESS_THAN(v)  ([[[UIDevice 
 currentDevice] systemVersion] compare:v options:NSNumericSearch] == 
 NSOrderedAscending)


CLLocationManager *locationManager;

-(void) checkLocationServicesAndStartUpdates
{
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
    {
        [locationManager requestWhenInUseAuthorization];
    }

    //Checking authorization status
    if (![CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)
    {

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Location Services Disabled!"
                                                            message:@"Please enable Location Based Services for better results! We promise to keep your location private"
                                                           delegate:self
                                                  cancelButtonTitle:@"Settings"
                                                  otherButtonTitles:@"Cancel", nil];

        //TODO if user has not given permission to device
        if (![CLLocationManager locationServicesEnabled])
        {
            alertView.tag = 100;
        }
        //TODO if user has not given permission to particular app
        else
        {
            alertView.tag = 200;
        }

        [alertView show];

        return;
    }
    else
    {
        //Location Services Enabled, let's start location updates
        [locationManager startUpdatingLocation];
    }
}

Обработайте пользовательский щелчок респон, и запустите правильные настройки местоположения

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

    if(buttonIndex == 0)//Settings button pressed
    {
        if (alertView.tag == 100)
        {
            //This will open ios devices location settings
            NSString* url = SYSTEM_VERSION_LESS_THAN(@"10.0") ? @"prefs:root=LOCATION_SERVICES" : @"App-Prefs:root=Privacy&path=LOCATION";
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];
        }
        else if (alertView.tag == 200)
        {
            //This will opne particular app location settings
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
        }
    }
    else if(buttonIndex == 1)//Cancel button pressed.
    {
        //TODO for cancel
    }
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{

    NSLog(@"%@",error.userInfo);
    if([CLLocationManager locationServicesEnabled]){

        NSLog(@"Location Services Enabled");

        if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
         UIAlertView    *alert = [[UIAlertView alloc] initWithTitle:@"App Permission Denied"
                                               message:@"To re-enable, please go to Settings and turn on Location Service for this app."
                                              delegate:nil
                                     cancelButtonTitle:@"OK"
                                     otherButtonTitles:nil];
            [alert show];
        }
    }
 }

Причина этого заключается в том, что этот метод будет вызываться, когда ваша служба отключит службу определения местоположения. этот код полезен для меня.

Проверьте свойство locationServicesEnabled объекта CLLocationManager, чтобы проверить доступность всей системы. Используйте locationManager: didFailWithError: метод вашего CLLocationManagerDelegate и проверьте, нет ли ошибки kCLErrorDenied, чтобы узнать, отклонил ли пользователь службы определения местоположения.

BOOL locationAllowed = [CLLocationManager locationServicesEnabled];
 if (!locationAllowed) 
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location Service Disabled" 
                                                        message:@"To re-enable, please go to Settings and turn on Location Service for this app." 
                                                       delegate:nil 
                                              cancelButtonTitle:@"OK" 
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
}

для вашего приложения используйте этот код

- (void)viewDidLoad
{
    locationManager = [[CLLocationManager alloc] init];

    locationManager.delegate = self;

    locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;

    // Set a movement threshold for new events.

    locationManager.distanceFilter = 500;

    [locationManager startUpdatingLocation];
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)locationManager:(CLLocationManager *)manager

     didUpdateLocations:(NSArray *)locations {

    // If it's a relatively recent event, turn off updates to save power

}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{

    NSLog(@"%@",error);
}

если служба определения местоположения отключена для вашего приложения, то выдает ошибку

Error Domain=kCLErrorDomain Code=1 "The operation couldn’t be completed. (kCLErrorDomain error 1.)"

Обновлено в последней версии Swift 5.0, Xcode 11.2.1

import UIKit
import CoreLocation

Константы пользователя

struct UserConstants {
    static let latitude = "latitude"
    static let longitude = "longitude"
    static let lastKnownLatitude = "lastKnownLatitude"
    static let lastKnownLongitude = "lastKnownLongitude"
}

Делегат диспетчера местоположения для отслеживания изменений местоположения

@objc protocol LocationManagerDelegate {
    @objc optional func getLocation(location: CLLocation)
}

class LocationHelper: NSObject, CLLocationManagerDelegate {

    weak var locationManagerDelegate: LocationManagerDelegate?
    var isLocationfetched: Bool = false
    var lastKnownLocation: CLLocation? {
        get {
            let latitude = UserDefaults.standard.double(forKey: UserConstants.lastKnownLatitude)
            let longitude = UserDefaults.standard.double(forKey: UserConstants.lastKnownLongitude)

            if latitude.isZero || longitude.isZero {
                return nil
            }
            return CLLocation(latitude: latitude, longitude: longitude)
        }
        set {
            UserDefaults.standard.set(newValue?.coordinate.latitude ?? 0, forKey: UserConstants.lastKnownLatitude)
            UserDefaults.standard.set(newValue?.coordinate.longitude ?? 0, forKey: UserConstants.lastKnownLongitude)
            UserDefaults.standard.synchronize()
        }
    }

    struct SharedInstance {
        static let instance = LocationHelper()
    }

    class var shared: LocationHelper {
        return SharedInstance.instance
    }

    enum Request {
        case requestWhenInUseAuthorization
        case requestAlwaysAuthorization
    }

    var clLocationManager = CLLocationManager()

    func setAccuracy(clLocationAccuracy: CLLocationAccuracy) {
        clLocationManager.desiredAccuracy = clLocationAccuracy
    }

    var isLocationEnable: Bool = false {
        didSet {
            if !isLocationEnable {
                lastKnownLocation = nil
            }
        }
    }

Обновление местоположения с проверкой авторизации

    func startUpdatingLocation() {
        isLocationfetched = false
        if CLLocationManager.locationServicesEnabled() {
            switch CLLocationManager.authorizationStatus() {
            case .notDetermined:
                clLocationManager.delegate = self
                clLocationManager.requestWhenInUseAuthorization()
                clLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
                clLocationManager.startUpdatingLocation()
                isLocationEnable = true
            case .restricted, .denied:
                showLocationAccessAlert()
                isLocationEnable = false
            case .authorizedAlways, .authorizedWhenInUse:
                self.clLocationManager.delegate = self
                self.clLocationManager.startUpdatingLocation()
                isLocationEnable = true
            default:
                print("Invalid AuthorizationStatus")
            }
        } else {
            isLocationEnable = false
            showLocationAccessAlert()
        }
    }

Показывать оповещение о местоположении, если разрешение не разрешено

    func showLocationAccessAlert() {
        let alertController = UIAlertController(title: "Location Permission Required", message: "Please enable location permissions in settings.", preferredStyle: UIAlertController.Style.alert)
        let okAction = UIAlertAction(title: "settings", style: .default, handler: {(cAlertAction) in
            UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
        })
        let cancelAction = UIAlertAction(title: "cancel", style: UIAlertAction.Style.cancel)
        alertController.addAction(cancelAction)
        alertController.addAction(okAction)
        let appdelegate = UIApplication.shared.delegate as? AppDelegate
        appdelegate?.window?.rootViewController?.present(alertController, animated: true, completion: nil)
    }

    func stopUpdatingLocation() {
        self.clLocationManager.stopUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if !isLocationfetched {
            isLocationfetched = true
            clLocationManager.startMonitoringSignificantLocationChanges()
            NotificationCenter.default.post(name: NSNotification.Name.updateLocationNotification, object: nil)
        }
        let userLocation = locations[0] as CLLocation
        self.lastKnownLocation = userLocation
        if let delegate = self.locationManagerDelegate {
            delegate.getLocation!(location: userLocation)
        }
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if (status == CLAuthorizationStatus.denied) {
            // The user denied authorization
            isLocationEnable = false
        } else if (status == CLAuthorizationStatus.authorizedWhenInUse) {
            // The user accepted authorization
            self.clLocationManager.delegate = self
            self.clLocationManager.startUpdatingLocation()
            isLocationEnable = true
        }
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("\n error description for location updation:- \(error.localizedDescription)")
    }

}

Для тестирования выше просто напишите эту строку кода в своем контроллере,

LocationHelper.shared.locationManagerDelegate = self
LocationHelper.shared.startUpdatingLocation()

LocationManagerDelegate методы

extension ViewController: LocationManagerDelegate {

    func getLocation(location: CLLocation) {
        currentLocation = location.coordinate
    }

}

После большого расследования. Я бы порекомендовал отображать это сообщение на ярлыке, а не в виде предупреждения. потому что есть много случаев, чтобы проверить (пользователь отключает службу определения местоположения в целом или только для приложения. удалить приложение, переустановить).

В одном из этих случаев ваше оповещение одновременно показывает ваше сообщение вместе с сообщением Apple. Ваше предупреждение будет за предупреждением Apple. что является запутанным и нелогичным поведением.

Я рекомендую следующее:

Свифт 3:

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

    switch status {
        case .notDetermined:
            Log.verbose("User still thinking granting location access!")
            manager.startUpdatingLocation() // this will access location automatically if user granted access manually. and will not show apple's request alert twice. (Tested)
        break

        case .denied:
            Log.verbose("User denied location access request!!")
            // show text on label
            label.text = "To re-enable, please go to Settings and turn on Location Service for this app."

            manager.stopUpdatingLocation()
            loadingView.stopLoading()
        break

        case .authorizedWhenInUse:
            // clear text
            label.text = ""
            manager.startUpdatingLocation() //Will update location immediately
        break

        case .authorizedAlways:
            // clear text
            label.text = ""
            manager.startUpdatingLocation() //Will update location immediately
        break
        default:
            break
    }
}

Objective-C:

- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    switch (status) {
        case kCLAuthorizationStatusNotDetermined: {
            DDLogVerbose(@"User still thinking granting location access!");
            [locationManager startUpdatingLocation]; // this will access location automatically if user granted access manually. and will not show apple's request alert twice. (Tested)
        } break;
        case kCLAuthorizationStatusDenied: {
            DDLogVerbose(@"User denied location access request!!");
            // show text on label
            label.text = @"To re-enable, please go to Settings and turn on Location Service for this app.";

            [locationManager stopUpdatingLocation];
            [loadingView stopLoading];
        } break;
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        case kCLAuthorizationStatusAuthorizedAlways: {
            // clear text
            label.text = @"";
            [locationManager startUpdatingLocation]; //Will update location immediately
        } break;
        default:
            break;
    }
}

Лучший способ справиться со всеми делами! ->

//First, checking if the location services are enabled
if(![CLLocationManager locationServicesEnabled]){
    [self showMessage:@"Please enable location services to detect location!" withTitle:@"Location not enabled"];
}
else if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
    //Now if the location is denied.
    UIAlertController *alertController = [UIAlertController
                                          alertControllerWithTitle:@"Enable location permission"
                                          message:@"To auto detect location, please enable location services for this app"
                                          preferredStyle:UIAlertControllerStyleAlert];

    alertController.view.tintColor = AppColor;
    UIAlertAction *cancelAction = [UIAlertAction
                                   actionWithTitle:@"Dismiss"
                                   style:UIAlertActionStyleCancel
                                   handler:^(UIAlertAction *action)
                                   {
                                        NSLog(@"Cancel action");
                                   }];

    UIAlertAction *goToSettings = [UIAlertAction
                                actionWithTitle:@"Settings"
                                style:UIAlertActionStyleDefault
                                handler:^(UIAlertAction *action)
                                {
                                    //Simple way to open settings module
                                    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                                    [[UIApplication sharedApplication] openURL:url];
                                }];

    [alertController addAction:cancelAction];
    [alertController addAction:goToSettings];
    [self presentViewController:alertController animated:YES completion:^{
        alertController.view.tintColor = AppColor;
    }];
}
else{
    //Do whatever you want here
}

Решение Swift 3.0 и iOS 10:


self.locationManager?.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() && CLLocationManager.authorizationStatus() != CLAuthorizationStatus.denied {
            locationManager?.delegate = self
            locationManager?.desiredAccuracy = kCLLocationAccuracyBestForNavigation
            locationManager?.distanceFilter = distanceFiler
            locationManager?.startUpdatingLocation()
        }else{
            let alertView = UIAlertView(title: "Location Services Disabled!", message: "Please enable Location Based Services for better results! We promise to keep your location private", delegate: self, cancelButtonTitle: "Settings", otherButtonTitles: "Cancel")
            alertView.delegate = self
            alertView.show()
            return
        }


@objc(alertView:clickedButtonAtIndex:) func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
    if buttonIndex == 0 {
            if let url = URL(string: "App-Prefs:root=LOCATION_SERVICES") {
                UIApplication.shared.open(url, completionHandler: .none)
            }
    }
    else if buttonIndex == 1 {
        //TODO for cancel
    }

}
Другие вопросы по тегам