繁体   English   中英

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

[英]How can I prompt the user to turn on location services after user has denied their use

我有一个具有明确用户交互的应用程序,它利用了用户的当前位置。 如果用户拒绝访问位置服务,我仍然希望后续用户提示用户转到设置并为我的应用重新启用位置服务。

我想要的行为是内置的地图应用程序的行为:

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

在我自己的应用程序中,相同的基本流程导致我的CLLocationManagerDelegate -locationManager:didFailWithError:方法在最后一步调用kCLErrorDenied错误,并且用户没有选择打开Settings应用程序来纠正它。

我可以显示自己的警报以响应错误,但是它无法启动“设置”应用程序,就像操作系统可以提供内置地图应用程序所使用的警报一样。

CLLocationManager类中有什么东西我错过了能够给我这个行为吗?

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

更新:

从iOS 8开始,现在有一个常量UIApplicationOpenSettingsURLString ,它表示一个URL,当打开该URL时,会将Settings应用程序打开到应用程序的设置(然后用户可以重新启用位置服务)。


原版的:

你无法做到这一点。 您唯一真正的选择是显示一条警报,通知用户您的应用程序需要位置服务,并指示他们手动转到“设置”应用并将其打开。

在iOS 8中不推荐使用 AlertView。现在有一种更好的方法可以使用新的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];

根据Apple的Docs上的LocationServicesEnabled方法。

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

您应该在开始位置更新之前检查此方法的返回值,以确定用户是否为当前设备启用了位置服务。 如果此方法返回NO并且您仍然启动位置更新,则Core Location框架会提示用户确认是否应重新启用位置服务。

所以你不能以任何方式启动位置服务更新以提示警报?

这是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)

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

   }
}

我想当Apple考虑新的SDK时,你会得到一个问题的答案。 目前,据我所知,这是不可能的:

没有可用的URL处理程序
没有可用的方法来打电话

但是......正如地图所做的那样,这可以完成,但可能使用私有API。 如果你不害怕这种编码,你应该在我看来搜索那里。

这是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)

斯威夫特

禁用应用程序的位置服务后,位置管理器委派方法将开始显示错误。 因此,在收到错误时,我们可以检查是否启用了位置服务。 根据结果​​,我们可以要求用户转到设置并打开位置服务。

在您的位置管理器委托方法中,请添加位置权限检查

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

用于创建设置警报控制器的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
    }
}

基于以上答案的最新swift版本。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM