问题
How can I check if location service is enabled for my app?
I have 2 storyboards and I want to check location service. If location service enabled for my app, I want to launch map storyboard with location. Otherwise, I want to launch another storyboard. How can I do programmatically?
回答1:
This is the correct.
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];
}
}
回答2:
Tested on iOS 9.2
For getting location updates we should always check
- Location services enabled on user's iOS Device and
- Location services enabled for particular app
and launching user on correct settings screen to enable
Launch iOS Device Location Settings page
Step.1 Go to Project settings --> Info --> URL Types --> Add New URL Schemes
Step.2 Use below code to launch direct phone's location settings page: (Note: The URL Scheme is different in iOS 10+, we check the version as stated here)
#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]];
Launch Application Location Settings page
Use below code to launch direct application's location settings page
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
Here is the full code example :
#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];
}
}
Handle the user click respone, and launch correct location settings
-(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
}
}
回答3:
-(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];
}
}
}
Reason behind this, this method will call when your service will be disable the location service. this code is useful for me.
回答4:
Check CLLocationManager's locationServicesEnabled property to check the system-wide availability. Use your CLLocationManagerDelegate's locationManager: didFailWithError: method and check for a kCLErrorDenied error to see if the user denied location services.
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];
}
for your app use this code
- (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);
}
if location service disable for your app then its give you error
Error Domain=kCLErrorDomain Code=1 "The operation couldn’t be completed. (kCLErrorDomain error 1.)"
回答5:
After a lot of investigation. I would recommend to display this message on a label and not on an alert view. because, there are a lot of cases to test against(user disables location service in general or just for app. delete app, reinstall).
One of these cases causes your alert to show your message along with apple's alert message at the same time. your alert will be behind apple's alert. which is a confusing and un-logical behavior.
I recommend the following:
Swift 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;
}
}
回答6:
The best way, handling all cases! ->
//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
}
回答7:
Swift 3.0 & iOS 10 Solution:
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
}
}
来源:https://stackoverflow.com/questions/15153074/checking-location-service-permission-on-ios