【问题标题】:Check if location services are enabled检查是否启用了定位服务
【发布时间】:2016-04-24 01:11:47
【问题描述】:

我一直在对 CoreLocation 进行一些研究。最近,我遇到了一个在其他地方已经讨论过的问题,但在 Objective C 和 iOS 8 中。

我觉得问这个有点傻,但是你如何检查是否在 iOS 9 上使用 swift 启用了定位服务?

在 iOS 7(也许是 8?)上,您可以使用 locationServicesEnabled(),但在为 iOS 9 编译时似乎不起作用。

那么我该如何实现呢?

谢谢!

【问题讨论】:

    标签: ios swift xcode location


    【解决方案1】:

    CLLocationManagerDelegate 添加到您的类继承中,然后您可以进行此检查:

    导入 CoreLocation 框架

    import CoreLocation
    

    Swift 1.x - 2.x 版本:

    if CLLocationManager.locationServicesEnabled() {
        switch CLLocationManager.authorizationStatus() {
        case .NotDetermined, .Restricted, .Denied:
            print("No access")
        case .AuthorizedAlways, .AuthorizedWhenInUse:
            print("Access")
        }
    } else {
        print("Location services are not enabled")
    }
    

    Swift 4.x 版本:

    if CLLocationManager.locationServicesEnabled() {
         switch CLLocationManager.authorizationStatus() {
            case .notDetermined, .restricted, .denied:
                print("No access")
            case .authorizedAlways, .authorizedWhenInUse:
                print("Access")
         }
    } else {
        print("Location services are not enabled")
    }
    

    Swift 5.1 版本

    if CLLocationManager.locationServicesEnabled() {
        switch CLLocationManager.authorizationStatus() {
            case .notDetermined, .restricted, .denied:
                print("No access")
            case .authorizedAlways, .authorizedWhenInUse:
                print("Access")
            @unknown default:
                break
        }
    } else {
        print("Location services are not enabled")
    }
    

    iOS 14.x

    在 iOS 14 中,您将收到以下错误消息: authorizationStatus() 在 iOS 14.0 中已弃用

    要解决此问题,请使用以下命令:
    private let locationManager = CLLocationManager()
    
    if CLLocationManager.locationServicesEnabled() {
        switch locationManager.authorizationStatus {
            case .notDetermined, .restricted, .denied:
                print("No access")
            case .authorizedAlways, .authorizedWhenInUse:
                print("Access")
            @unknown default:
                break
        }
    } else {
        print("Location services are not enabled")
    }
    

    【讨论】:

    • 是的!谢谢!我的问题是我试图在我的经理上调用 locatoinServicesEnabled,即 manager.locationServicesEnabled() 而不是 CLLocationManager.loationServicesEnabled() 已解决!
    • 我知道您的代码只是一个示例,但它有点误导......我认为最好将authorizationStatus 设置 设置为notDetermined 然后而不是只是记录它会更好地提示用户“允许/不允许”
    • @Honey,当然你可以随意使用它,正如你所说,代码只是展示如何使用它的示例。
    【解决方案2】:

    在objective-c中

    您应该跟踪已被拒绝或未确定的用户,然后请求许可或将用户发送到设置应用程序。

    -(void)askEnableLocationService
    {
       BOOL showAlertSetting = false;
       BOOL showInitLocation = false;
    
       if ([CLLocationManager locationServicesEnabled]) {
    
          switch ([CLLocationManager authorizationStatus]) {
            case kCLAuthorizationStatusDenied:
                showAlertSetting = true;
                NSLog(@"HH: kCLAuthorizationStatusDenied");
                break;
            case kCLAuthorizationStatusRestricted:
                showAlertSetting = true;
                NSLog(@"HH: kCLAuthorizationStatusRestricted");
                break;
            case kCLAuthorizationStatusAuthorizedAlways:
                showInitLocation = true;
                NSLog(@"HH: kCLAuthorizationStatusAuthorizedAlways");
                break;
            case kCLAuthorizationStatusAuthorizedWhenInUse:
                showInitLocation = true;
                NSLog(@"HH: kCLAuthorizationStatusAuthorizedWhenInUse");
                break;
            case kCLAuthorizationStatusNotDetermined:
                showInitLocation = true;
                NSLog(@"HH: kCLAuthorizationStatusNotDetermined");
                break;
            default:
                break;
          }
       } else {
    
          showAlertSetting = true;
          NSLog(@"HH: locationServicesDisabled");
      }
    
       if (showAlertSetting) {
           UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"Please enable location service for this app in ALLOW LOCATION ACCESS: Always, Go to Setting?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Open Setting", nil];
           alertView.tag = 199;
           [alertView show];
       }
       if (showInitLocation) {
           [self initLocationManager];
       }
    
    }
    

    如果已经被用户拒绝,则执行 alertView Delegate 然后发送用户启用位置服务。

    -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
    
       if (alertView.tag == 199) {
           if (buttonIndex == 1) {
               [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
           }
           return;
       }
    }
    

    初始化位置管理器

    -(void)initLocationManager{
       self.locationManager = [[CLLocationManager alloc] init];
       if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
           [self.locationManager requestAlwaysAuthorization];
       }
    }
    

    请注意 kCLAuthorizationStatusAuthorizedAlways 和 kCLAuthorizationStatusAuthorizedWhenInUse 的区别。

    【讨论】:

    • 感谢这个objective-c版本,虽然最初的问题是关于swift的。附加提示:如果未确定状态,则调用 requestWhenInUseAuthorization,为使用说明设置相关的 plist 条目(可能已本地化),并可能实现 didChangeAuthorizationStatus
    【解决方案3】:

    这是Apple推荐的格式。

      switch CLLocationManager.authorizationStatus() {
          case .notDetermined:
             // Request when-in-use authorization initially
             break
          case .restricted, .denied:
             // Disable location features
             break
          case .authorizedWhenInUse, .authorizedAlways:
             // Enable location features
             break
          }
    

    这是一个完整的例子。

    这包括一个带有按钮的AlertView,如果之前被拒绝访问,该按钮可将用户带到Settings 屏幕。

    import CoreLocation
    let locationManager = CLLocationManager()
    
    class SettingsTableViewController:CLLocationManagerDelegate{
    
        func checkUsersLocationServicesAuthorization(){
            /// Check if user has authorized Total Plus to use Location Services
            if CLLocationManager.locationServicesEnabled() {
                switch CLLocationManager.authorizationStatus() {
                case .notDetermined:
                    // Request when-in-use authorization initially
                    // This is the first and the ONLY time you will be able to ask the user for permission
                    self.locationManager.delegate = self
                    locationManager.requestWhenInUseAuthorization()
                    break
    
                case .restricted, .denied:
                    // Disable location features
                    switchAutoTaxDetection.isOn = false
                    let alert = UIAlertController(title: "Allow Location Access", message: "MyApp needs access to your location. Turn on Location Services in your device settings.", preferredStyle: UIAlertController.Style.alert)
    
                    // Button to Open Settings
                    alert.addAction(UIAlertAction(title: "Settings", style: UIAlertAction.Style.default, handler: { action in
                        guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
                            return
                        }
                        if UIApplication.shared.canOpenURL(settingsUrl) {
                            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                                print("Settings opened: \(success)") 
                            })
                        }
                    }))
                    alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
                    self.present(alert, animated: true, completion: nil)
    
                    break
    
                case .authorizedWhenInUse, .authorizedAlways:
                    // Enable features that require location services here.
                    print("Full Access")
                    break
                }
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      SWIFT (截至 2018 年 7 月 24 日)

      if CLLocationManager.locationServicesEnabled() {
      
      }
      

      这将告诉您用户是否已经为应用的位置权限请求选择了设置

      【讨论】:

        【解决方案5】:

        它只是 Swift 4 中的一个 2 行函数:

        import CoreLocation
        
        static func isLocationPermissionGranted() -> Bool
        {
            guard CLLocationManager.locationServicesEnabled() else { return false }
            return [.authorizedAlways, .authorizedWhenInUse].contains(CLLocationManager.authorizationStatus())
        }
        

        【讨论】:

          【解决方案6】:

          对于 swift3.0 及以上版本, 如果经常检查位置服务的可用性,请创建一个如下所示的类,

              import CoreLocation
          
              open class Reachability {
                  class func isLocationServiceEnabled() -> Bool {
                      if CLLocationManager.locationServicesEnabled() {
                          switch(CLLocationManager.authorizationStatus()) {
                              case .notDetermined, .restricted, .denied:
                              return false
                              case .authorizedAlways, .authorizedWhenInUse:
                              return true
                              default:
                              print("Something wrong with Location services")
                              return false
                          }
                      } else {
                              print("Location services are not enabled")
                              return false
                        }
                      }
                   }
          

          然后在你的 VC 中像这样使用它

              if Reachability.isLocationServiceEnabled() == true {
              // Do what you want to do.
              } else {
              //You could show an alert like this.
                  let alertController = UIAlertController(title: "Location 
                  Services Disabled", message: "Please enable location services 
                  for this app.", preferredStyle: .alert)
                  let OKAction = UIAlertAction(title: "OK", style: .default, 
                  handler: nil)
                  alertController.addAction(OKAction)
                  OperationQueue.main.addOperation {
                      self.present(alertController, animated: true, 
                      completion:nil)
                  }
              }
          

          【讨论】:

            【解决方案7】:

            当您调用 -startLocation 时,如果用户拒绝了位置服务,则位置管理器委托将收到对 -locationManager:didFailWithError: 的调用,并带有 kCLErrorDenied 错误代码。这适用于所有版本的 iOS。

            【讨论】:

            • 谢谢。不幸的是,当我尝试这样做时,它显示:Use of unresolved identifier 'kCLErrorDenied'。想法?
            【解决方案8】:

            在 Swift 3.0 中

            if (CLLocationManager.locationServicesEnabled())
                        {
                            locationManager.delegate = self
                            locationManager.desiredAccuracy = kCLLocationAccuracyBest
                            if ((UIDevice.current.systemVersion as NSString).floatValue >= 8)
                            {
                                locationManager.requestWhenInUseAuthorization()
                            }
            
                            locationManager.startUpdatingLocation()
                        }
                        else
                        {
                            #if debug
                                println("Location services are not enabled");
                            #endif
                        }
            

            【讨论】:

              【解决方案9】:

              为您使用的定位服务请求许可:

              yourSharedLocationManager.requestWhenInUseAuthorization()
              

              如果当前状态未确定,则会显示警报,提示用户允许访问。如果访问被拒绝,您的应用将在 CLLocationManagerDelegate 中收到通知,同样,如果权限在任何时候被拒绝,您将在此处更新。

              您需要检查两种不同的状态以确定当前权限。

              • 用户是否启用了一般定位服务

              CLLocationManager.locationServicesEnabled()

              • 如果用户为您的应用授予了正确的权限..

              CLLocationManager.authorizationStatus() == .authorizedWhenInUse

              您可以添加一个扩展是一个方便的选择:

              extension CLLocationManager {
              static func authorizedToRequestLocation() -> Bool {
                  return CLLocationManager.locationServicesEnabled() &&
                      (CLLocationManager.authorizationStatus() == .authorizedAlways || CLLocationManager.authorizationStatus() == .authorizedWhenInUse)
              }
              

              }

              当用户第一次请求路线时,它正在被访问:

               private func requestUserLocation() {
                  //when status is not determined this method runs to request location access
                  locationManager.requestWhenInUseAuthorization()
              
                  if CLLocationManager.authorizedToRequestLocation() {
              
                      //have accuracy set to best for navigation - accuracy is not guaranteed it 'does it's best'
                      locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
              
                      //find out current location, using this one time request location will start the location services and then stop once have the location within the desired accuracy -
                      locationManager.requestLocation()
                  } else {
                      //show alert for no location permission
                      showAlertNoLocation(locationError: .invalidPermissions)
                  }
              }
              

              这是代表:

               func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
              
                  if !CLLocationManager.authorizedToRequestLocation() {
                      showAlertNoLocation(locationError: .invalidPermissions)
                  }
              }
              

              【讨论】:

                【解决方案10】:

                Swift 5.2

                首先,将 User 类设置为 CLLocationManager 委托:

                class User: NSObject, ObservableObject {
                
                   let manager = CLLocationManager()
                
                   override init() {
                      super.init()
                      manager.delegate = self
                      manager.requestWhenInUseAuthorization()
                      manager.requestLocation()
                      manager.startUpdatingLocation()
                   }
                }
                
                extension User: CLLocationManagerDelegate {
                
                   func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
                      print("Location services authorization request")
                   }
                
                   func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                      print("Location updated")
                   }
                
                   func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
                      print("Failed to find user's location: \(error.localizedDescription)")
                   }
                 }
                

                然后在一个视图中:

                if (user.manager.authorizationStatus == .denied) {
                   print("Location authorization denied, displaying sheet.")      
                }
                

                【讨论】:

                  猜你喜欢
                  • 2014-08-22
                  • 1970-01-01
                  • 2021-03-07
                  • 2011-06-22
                  • 1970-01-01
                  • 2015-12-02
                  • 2016-08-15
                  相关资源
                  最近更新 更多