我的应用程序具有明确的用户交互,可以利用用户的当前位置。如果用户拒绝访问位置服务,我仍然希望后续用户提示用户转到设置并为我的应用重新启用位置服务。
我想要的行为是内置地图应用的行为:
在我自己的应用程序中,相同的基本流程导致我的CLLocationManagerDelegate -locationManager:didFailWithError:方法在最后一步调用kCLErrorDenied错误,并且用户没有选择打开Settings应用程序来纠正它。 / p>
我可以显示自己的警报以响应错误,但它无法启动“设置”应用,就像操作系统可以提供内置地图应用使用的警报一样。
CLLocationManager类中是否有一些我遗漏的东西可以给我这种行为?
答案 0 :(得分:42)
使用iOS8,您最终可以通过openURL将用户链接到“设置”应用。例如,您可以使用单个按钮创建UIAlertView,该按钮将用户带到“设置”应用程序:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ICLocalizedString(@"LocationServicesPermissionTitle")
message:ICLocalizedString(@"LocationPermissionGeoFenceMessage")
delegate:self
cancelButtonTitle:@"Settings"
otherButtonTitles:nil];
[alert show];
在您的UIAlertView委托中:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
}
答案 1 :(得分:32)
<强>更新强>
从iOS 8开始,现在有一个常量UIApplicationOpenSettingsURLString
表示一个URL,当打开该URL时,会打开设置应用程序到您的应用程序的设置(然后用户可以重新启用位置服务)。
<强>原始强>
你无法做到这一点。您唯一真正的选择是显示一条警报,通知用户您的应用程序需要位置服务,并指示他们手动转到“设置”应用并将其打开。
答案 2 :(得分:16)
AlertViews 已弃用。现在有一种更好的方法可以使用新的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];
答案 3 :(得分:6)
根据 locationServicesEnabled 方法的Apple's Docs。
用户可以通过在常规中切换位置服务开关,从“设置”应用程序启用或禁用位置服务。
您应该在开始位置更新之前检查此方法的返回值,以确定用户是否为当前设备启用了位置服务。 如果此方法返回NO并且您仍然启动位置更新,则Core Location框架会提示用户确认是否应重新启用位置服务。
你不能以任何方式启动位置服务更新以引发警报吗?
答案 4 :(得分:6)
这是Markus和bjc提供的代码的快速3实现。
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.shared.openURL(NSURL(string: UIApplicationOpenSettingsURLString)! as URL)
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.present(alertController, animated: true, completion: nil)
答案 5 :(得分:3)
在Swift 4中,语法有了更新。
Swift 4
q
答案 6 :(得分:2)
我想当Apple考虑新的SDK时,你会得到一个问题的答案。目前,据我所知,这是不可能的:
没有可用的URL处理程序
没有可用的方法来调用
但是......正如地图那样,这可以完成,但可能使用私有API。如果你不害怕这种编码,你应该在我看来搜索那里。
答案 7 :(得分:1)
这是Markus在答案中的Swift版本代码。此代码会创建一个警报,为用户提供打开“设置”的选项。
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)
答案 8 :(得分:1)
<强>夫特强>,
为应用程序禁用位置服务后,位置管理器委派方法将开始显示错误。因此,在收到错误时,我们可以检查是否启用了位置服务。根据结果,我们可以要求用户转到设置并打开位置服务。
在您的位置管理器委托方法中输入错误,添加位置权限检查
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
//check location permissions
self.checkLocationPermission()
}
}
位置权限检查代码
//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: ""))
}
}
打开设置应用的代码,
//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)
}
答案 9 :(得分:0)
基于上述答案的最新快速版本。
func showSettingsAlert(_ from:UIViewController, 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
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
}
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
from.present(alertController, animated: true, completion: nil)
}