在用户拒绝使用位置服务后,如何提示用户打开位置服务


75

我有一个具有显式用户交互的应用程序,该应用程序利用了用户的当前位置。如果用户拒绝访问位置服务,我仍然希望随后的使用提示用户进入设置并为我的应用重新启用位置服务。

我想要的行为是内置Maps应用的行为:

  1. 在设置>常规>重置>重置位置警告中重置位置警告。
  2. 启动地图应用。
  3. 点击左下角的当前位置按钮。
  4. 具有““地图”的地图提示将要使用您的当前位置“ | “不允许” | “允许”。
  5. 选择“不允许”选项。
  6. 再次点击左下角的当前位置按钮。
  7. 地图提示“打开位置服务以允许“地图”确定您的位置” | “设置” | “取消”。

在我自己的应用程序中,相同的基本流程导致我的CLLocationManagerDelegate -locationManager:didFailWithError:方法在最后一步被调用,并带有kCLErrorDenied错误,并且用户没有选择打开“设置”应用程序进行更正的选项。

我可以显示我自己的警报来响应该错误,但是它无法像操作系统内置的Maps应用所使用的警报那样启动“设置”应用。

我缺少的CLLocationManager类中有什么能够给我这种​​行为的吗?


现在,我只是向用户显示警报,要求他们转到“设置”以重新启用它。我也想听听更好的解决方案。
donkim 2011年

我也想回答这个问题,肯定有更好的方法
conorgriffin

由于这个原因,我发现CoreLocation并不令人满意。我最终使用了易于集成且文档详尽的skyhook库。坐标似乎也更精确。唯一的缺点是必须将1.5MB dylib与该应用程序捆绑在一起。
克里斯·莫福斯

我认为许多答案都显示出stackoverflow.com/questions/5655674/…的
Pramod更多

Answers:


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

4
这比在iOS 7和更早版本中可以做的要好得多,但是仍然不够完美,因为URL会将您带到用户可以实际更改设置的上一级屏幕。
GBegen 2014年

至少从iOS 10开始,它将带您直接进入应用设置,同时还会列出位置。
西藏沿海地区,2013年

32

更新:

从iOS 8开始,现在存在UIApplicationOpenSettingsURLString代表URL的常量,该常量在打开时会打开“设置”应用程序到您应用程序的设置(然后用户可以在其中重新启用位置服务)。


原版的:

您无法执行此操作。您唯一的实际选择是显示警报,以通知用户您的应用程序需要位置服务,并指示他们手动转到“设置”应用程序并将其打开。


我已经阅读了Apple Docs,并在下面根据文档发布了答案,但我没有亲自测试过。这是SDK的更改还是相同的。
只是一名编码员

恐怕这个答案不再正确。您可能希望更新或删除答案。
James Webster

这是Swift nshipster.com/core-location-in-ios-8中的一个很好的例子,我发现它真的很有帮助。它显示了如何发出重定向到Settingsusing的警报UIApplicationOpenSettingsURLString
dmk12 '04

17

iOS 8中不建议使用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];

7

根据Apple的Docs上的locationServicesEnabled方法。

用户通常可以通过切换“位置服务”开关来从“设置”应用程序启用或禁用位置服务。

您应该在开始位置更新之前检查此方法的返回值,以确定用户是否为当前设备启用了位置服务。如果此方法返回“否”并且无论如何您都开始位置更新,则“核心位置”框架会提示用户确认是否应重新启用位置服务。

那么,您能否以任何方式启动定位服务更新来引起警报提示?


15
它实际上不是以这种方式工作,可能与locationServicesEnabled和authorized之间的细微差别有关。如果禁用了它们,它将提示启用,但是如果启用但被拒绝,则将不执行任何操作。但是,这是非常令人困惑的文档。
SG1 2012年

locationServicesEnabled是已弃用的方法。
Ben Patch

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

在Swift 4中,其语法进行了更新。

斯威夫特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)

   }
}

2

我想当苹果考虑一个新的SDK时,您将对您的问题有一个答案。就目前而言,据我所知,这是不可能的:

没有可用的URL处理程序
没有可用的调用方法

但是...就像Maps一样,可以完成此操作,但可能使用私有API。如果您对这种编码不感到害怕,那么我认为应该在此处进行搜索。


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)

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

1

根据上述答案的最新的快速版本。

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

0

Swift 3扩展,用于创建设置警报控制器:

进口基金会

extension UIAlertController {
    func createSettingsAlertController(title: String, message: String) -> UIAlertController {
        let controller = 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, handler: { action in
            UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
        })
        controller.addAction(cancelAction)
        controller.addAction(settingsAction)

        return controller
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.