How can I check if location service is enabled for my app?
I have 2 storyboards and I want to check location service. If location service enabled for my app, I want
This is the correct.
if ([CLLocationManager locationServicesEnabled]){
NSLog(@"Location Services Enabled");
if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
alert = [[UIAlertView alloc] initWithTitle:@"App Permission Denied"
message:@"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
}
Tested on iOS 9.2
For getting location updates we should always check
and launching user on correct settings screen to enable
Launch iOS Device Location Settings page
Step.1 Go to Project settings --> Info --> URL Types --> Add New URL Schemes
Step.2 Use below code to launch direct phone's location settings page: (Note: The URL Scheme is different in iOS 10+, we check the version as stated here)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice
currentDevice] systemVersion] compare:v options:NSNumericSearch] ==
NSOrderedAscending)
//Usage
NSString* url = SYSTEM_VERSION_LESS_THAN(@"10.0") ? @"prefs:root=LOCATION_SERVICES" : @"App-Prefs:root=Privacy&path=LOCATION";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];
Launch Application Location Settings page
Use below code to launch direct application's location settings page
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
Here is the full code example :
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice
currentDevice] systemVersion] compare:v options:NSNumericSearch] ==
NSOrderedAscending)
CLLocationManager *locationManager;
-(void) checkLocationServicesAndStartUpdates
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[locationManager requestWhenInUseAuthorization];
}
//Checking authorization status
if (![CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Location Services Disabled!"
message:@"Please enable Location Based Services for better results! We promise to keep your location private"
delegate:self
cancelButtonTitle:@"Settings"
otherButtonTitles:@"Cancel", nil];
//TODO if user has not given permission to device
if (![CLLocationManager locationServicesEnabled])
{
alertView.tag = 100;
}
//TODO if user has not given permission to particular app
else
{
alertView.tag = 200;
}
[alertView show];
return;
}
else
{
//Location Services Enabled, let's start location updates
[locationManager startUpdatingLocation];
}
}
Handle the user click respone, and launch correct location settings
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)//Settings button pressed
{
if (alertView.tag == 100)
{
//This will open ios devices location settings
NSString* url = SYSTEM_VERSION_LESS_THAN(@"10.0") ? @"prefs:root=LOCATION_SERVICES" : @"App-Prefs:root=Privacy&path=LOCATION";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: url]];
}
else if (alertView.tag == 200)
{
//This will opne particular app location settings
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}
else if(buttonIndex == 1)//Cancel button pressed.
{
//TODO for cancel
}
}
Swift 3.0 & iOS 10 Solution:
self.locationManager?.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() && CLLocationManager.authorizationStatus() != CLAuthorizationStatus.denied {
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager?.distanceFilter = distanceFiler
locationManager?.startUpdatingLocation()
}else{
let alertView = UIAlertView(title: "Location Services Disabled!", message: "Please enable Location Based Services for better results! We promise to keep your location private", delegate: self, cancelButtonTitle: "Settings", otherButtonTitles: "Cancel")
alertView.delegate = self
alertView.show()
return
}
@objc(alertView:clickedButtonAtIndex:) func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
if buttonIndex == 0 {
if let url = URL(string: "App-Prefs:root=LOCATION_SERVICES") {
UIApplication.shared.open(url, completionHandler: .none)
}
}
else if buttonIndex == 1 {
//TODO for cancel
}
}
The best way, handling all cases! ->
//First, checking if the location services are enabled
if(![CLLocationManager locationServicesEnabled]){
[self showMessage:@"Please enable location services to detect location!" withTitle:@"Location not enabled"];
}
else if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
//Now if the location is denied.
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Enable location permission"
message:@"To auto detect location, please enable location services for this app"
preferredStyle:UIAlertControllerStyleAlert];
alertController.view.tintColor = AppColor;
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:@"Dismiss"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
NSLog(@"Cancel action");
}];
UIAlertAction *goToSettings = [UIAlertAction
actionWithTitle:@"Settings"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
//Simple way to open settings module
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url];
}];
[alertController addAction:cancelAction];
[alertController addAction:goToSettings];
[self presentViewController:alertController animated:YES completion:^{
alertController.view.tintColor = AppColor;
}];
}
else{
//Do whatever you want here
}
Updated in Latest Swift 5.0, Xcode 11.2.1
import UIKit
import CoreLocation
User constants
struct UserConstants {
static let latitude = "latitude"
static let longitude = "longitude"
static let lastKnownLatitude = "lastKnownLatitude"
static let lastKnownLongitude = "lastKnownLongitude"
}
Location Manager Delegate for monitoring location changes
@objc protocol LocationManagerDelegate {
@objc optional func getLocation(location: CLLocation)
}
class LocationHelper: NSObject, CLLocationManagerDelegate {
weak var locationManagerDelegate: LocationManagerDelegate?
var isLocationfetched: Bool = false
var lastKnownLocation: CLLocation? {
get {
let latitude = UserDefaults.standard.double(forKey: UserConstants.lastKnownLatitude)
let longitude = UserDefaults.standard.double(forKey: UserConstants.lastKnownLongitude)
if latitude.isZero || longitude.isZero {
return nil
}
return CLLocation(latitude: latitude, longitude: longitude)
}
set {
UserDefaults.standard.set(newValue?.coordinate.latitude ?? 0, forKey: UserConstants.lastKnownLatitude)
UserDefaults.standard.set(newValue?.coordinate.longitude ?? 0, forKey: UserConstants.lastKnownLongitude)
UserDefaults.standard.synchronize()
}
}
struct SharedInstance {
static let instance = LocationHelper()
}
class var shared: LocationHelper {
return SharedInstance.instance
}
enum Request {
case requestWhenInUseAuthorization
case requestAlwaysAuthorization
}
var clLocationManager = CLLocationManager()
func setAccuracy(clLocationAccuracy: CLLocationAccuracy) {
clLocationManager.desiredAccuracy = clLocationAccuracy
}
var isLocationEnable: Bool = false {
didSet {
if !isLocationEnable {
lastKnownLocation = nil
}
}
}
Location updates with authorization check
func startUpdatingLocation() {
isLocationfetched = false
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined:
clLocationManager.delegate = self
clLocationManager.requestWhenInUseAuthorization()
clLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
clLocationManager.startUpdatingLocation()
isLocationEnable = true
case .restricted, .denied:
showLocationAccessAlert()
isLocationEnable = false
case .authorizedAlways, .authorizedWhenInUse:
self.clLocationManager.delegate = self
self.clLocationManager.startUpdatingLocation()
isLocationEnable = true
default:
print("Invalid AuthorizationStatus")
}
} else {
isLocationEnable = false
showLocationAccessAlert()
}
}
Show location alert if permission is not allowed
func showLocationAccessAlert() {
let alertController = UIAlertController(title: "Location Permission Required", message: "Please enable location permissions in settings.", preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "settings", style: .default, handler: {(cAlertAction) in
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
})
let cancelAction = UIAlertAction(title: "cancel", style: UIAlertAction.Style.cancel)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
let appdelegate = UIApplication.shared.delegate as? AppDelegate
appdelegate?.window?.rootViewController?.present(alertController, animated: true, completion: nil)
}
func stopUpdatingLocation() {
self.clLocationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if !isLocationfetched {
isLocationfetched = true
clLocationManager.startMonitoringSignificantLocationChanges()
NotificationCenter.default.post(name: NSNotification.Name.updateLocationNotification, object: nil)
}
let userLocation = locations[0] as CLLocation
self.lastKnownLocation = userLocation
if let delegate = self.locationManagerDelegate {
delegate.getLocation!(location: userLocation)
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.denied) {
// The user denied authorization
isLocationEnable = false
} else if (status == CLAuthorizationStatus.authorizedWhenInUse) {
// The user accepted authorization
self.clLocationManager.delegate = self
self.clLocationManager.startUpdatingLocation()
isLocationEnable = true
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("\n error description for location updation:- \(error.localizedDescription)")
}
}
For testing above, just write these line of code in your controller,
LocationHelper.shared.locationManagerDelegate = self
LocationHelper.shared.startUpdatingLocation()
LocationManagerDelegate Methods
extension ViewController: LocationManagerDelegate {
func getLocation(location: CLLocation) {
currentLocation = location.coordinate
}
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(@"%@",error.userInfo);
if([CLLocationManager locationServicesEnabled]){
NSLog(@"Location Services Enabled");
if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"App Permission Denied"
message:@"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
}
}
Reason behind this, this method will call when your service will be disable the location service. this code is useful for me.