问题
I've been doing some research about CoreLocation. Recently, I encountered a problem that has been covered elsewhere, but in Objective C, and for iOS 8.
I feel kinda silly asking this, but how can you check if location services are enabled using swift, on iOS 9?
On iOS 7 (and maybe 8?) you could use locationServicesEnabled(), but that doesn't appear to be working when compiling for iOS 9.
So how would I accomplish this?
Thanks!
回答1:
Add the CLLocationManagerDelegate to your class inheritance and then you can make this check:
Swift 1.x - 2.x version:
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 version:
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 version
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")
}
回答2:
In objective-c
you should track user already denied or not determined then ask for permission or sent user to Setting app.
-(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];
}
}
Implement alertView Delegate then sent user to enable location service if already deny by user.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 199) {
if (buttonIndex == 1) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
return;
}
}
Init Location Manager
-(void)initLocationManager{
self.locationManager = [[CLLocationManager alloc] init];
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
}
Please note kCLAuthorizationStatusAuthorizedAlways and kCLAuthorizationStatusAuthorizedWhenInUse is difference.
回答3:
SWIFT (As of July 24, 2018)
if CLLocationManager.locationServicesEnabled() {
}
this will tell you if the user has already selected a setting for the app's location permission request
回答4:
For swift3.0 and above , if frequent checks are made for the availability of location services, create a class like below,
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
}
}
}
and then use it like this in your 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)
}
}
回答5:
It is just a 2 line function in Swift 4:
import CoreLocation
static func isLocationPermissionGranted() -> Bool
{
guard CLLocationManager.locationServicesEnabled() else { return false }
return [.authorizedAlways, .authorizedWhenInUse].contains(CLLocationManager.authorizationStatus())
}
回答6:
Here is the format Apple recommends.
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
}
Here is a complete example.
This includes an AlertView with a button to take the user to the Settings screen if previously denied access.
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
}
}
}
}
回答7:
When you call -startLocation, if location services were denied by the user, the location manager delegate will receive a call to - locationManager:didFailWithError: with the kCLErrorDenied error code. This works both in all versions of iOS.
回答8:
In 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:
To ask for permission for location services you use:
yourSharedLocationManager.requestWhenInUseAuthorization()
If the status is currently undetermined an alert will show prompting the user to allow access. If access is denied your app will be notified in the CLLocationManagerDelegate, likewise if permission is denied at any point you will be updated here.
There are two separate statuses you need to check to determine the current permissions.
- If the user has the general location services enabled or not
CLLocationManager.locationServicesEnabled()
- If the user has granted the correct permission for your app..
CLLocationManager.authorizationStatus() == .authorizedWhenInUse
You could add an extension is a handy option:
extension CLLocationManager {
static func authorizedToRequestLocation() -> Bool {
return CLLocationManager.locationServicesEnabled() &&
(CLLocationManager.authorizationStatus() == .authorizedAlways || CLLocationManager.authorizationStatus() == .authorizedWhenInUse)
}
}
Here it is being accessed when the user has first requested directions:
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)
}
}
Here is the delegate:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if !CLLocationManager.authorizedToRequestLocation() {
showAlertNoLocation(locationError: .invalidPermissions)
}
}
来源:https://stackoverflow.com/questions/34861941/check-if-location-services-are-enabled