I have an application with an explicit user interaction that makes use of the user\'s current location. If the user denies access to location services, I would still like su
I guess you will have an answer to your question when Apple will think about a new SDK. At current time and as far as I know, it's not possible :
No URL-Handler available
No usable method to call
But... As Maps does it, this CAN be done, but probably using a private API. If you're not afraid with this kind of coding, you should search there in my opinion.
Swift,
Once you disable location services for an app, location manager delegate methods will start showing error. So, on receiving error we can check if location services are enabled/disabled. And according to the result, we can ask the user to go to settings and turn on location services.
In your location manager delegate method for error, add location permission check
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
//check location permissions
self.checkLocationPermission()
}
}
Code for location permission checking
//check location services enabled or not
func checkLocationPermission() {
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .notDetermined, .restricted, .denied:
//open setting app when location services are disabled
openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
}
} else {
print("Location services are not enabled")
openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
}
}
Code to open settings app,
//open location settings for app
func openSettingApp(message: String) {
let alertController = UIAlertController (title: APP_NAME_TITLE, message:message , preferredStyle: .alert)
let settingsAction = UIAlertAction(title: NSLocalizedString("settings", comment: ""), style: .default) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
}
}
alertController.addAction(settingsAction)
let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .default, handler: nil)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
In Swift 4, there is an update in its syntax.
Swift 4
extension UIAlertController {
func createSettingsAlertController(title: String, message: String) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)! as URL, options: [:], completionHandler: nil)
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.present(alertController, animated: true, completion: nil)
}
}
Here's a Swift version of the code in the answer by Markus. This code creates an alert that gives the user the option to open Settings.
let alertController = UIAlertController(title: NSLocalizedString("Enter your title here", comment: ""), message: NSLocalizedString("Enter your message here.", comment: ""), preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .Default) { (UIAlertAction) in
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.presentViewController(alertController, animated: true, completion: nil)
With iOS8, you can finally link user to Settings app via openURL. For example, you can create a UIAlertView with a single button that takes user to the Settings app:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ICLocalizedString(@"LocationServicesPermissionTitle")
message:ICLocalizedString(@"LocationPermissionGeoFenceMessage")
delegate:self
cancelButtonTitle:@"Settings"
otherButtonTitles:nil];
[alert show];
In your UIAlertView delegate:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
}
AlertViews are deprecated in iOS 8. There is now a better way to handle alerts using the new AlertController:
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString( @"Enter your title here", @"" ) message:NSLocalizedString( @"Enter your message here.", @"" ) preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Cancel", @"" ) style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Settings", @"" ) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:
UIApplicationOpenSettingsURLString]];
}];
[alertController addAction:cancelAction];
[alertController addAction:settingsAction];
[self presentViewController:alertController animated:YES completion:nil];