首页 文章

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

提问于
浏览
69

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

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

  • 在设置>常规>重置>重置位置警告中重置位置警告 .

  • 启动 Map 应用 .

  • 点击左下角的当前位置按钮 .

  • Map 提示“"Maps"想要使用您的当前位置" | "不允许" | "允许” .

  • 选择"Don't Allow"选项 .

  • 再次点击左下角的当前位置按钮 .

  • Map 提示"Turn On Location Services to Allow " Map " to Determine Your Location" | "Settings" | "Cancel" .

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

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

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

11 回答

  • 32

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

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

    Update:

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


    Original:

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

  • 0

    在iOS 8中,AlertViews是 deprecated . 现在有一种更好的方法来使用新的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];
    
  • 1

    根据Apple's DocslocationServicesEnabled 方法 .

    用户可以通过在常规中切换位置服务开关,从“设置”应用程序启用或禁用位置服务 . 您应该在开始位置更新之前检查此方法的返回值,以确定用户是否为当前设备启用了位置服务 . 如果此方法返回NO并且您仍然启动位置更新,则Core Location框架会提示用户确认是否应重新启用位置服务 .

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

  • 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)
    
  • 2

    在Swift 4中,语法有了更新 .

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

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

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

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

  • 5

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

    Swift

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

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

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

    基于以上答案的最新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)
        }
    

相关问题