I am trying to update some old code to get it to work in IOS 8. I have read through
Location Services not working in iOS 8
but I am still very confused as to how to correctly implement the methodology.
I have added in
<key>NSLocationWhenInUseUsageDescription</key>
<string>The spirit of stack overflow is coders helping coders</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I have learned more on stack overflow than anything else</string>
into the infoPlist.strings
but I am not sure how to update my code to get it to execute properly. Here is a copy of the old code that I am using. Can anyone provide insight on how to properly update this code in order to get it to work with IOS 8?
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
NSLog(#"%s", __PRETTY_FUNCTION__);
switch (status) {
case kCLAuthorizationStatusAuthorizedAlways:
{
NSLog(#"kCLAuthorizationStatusAuthorized");
// Re-enable the post button if it was disabled before.
self.navigationItem.rightBarButtonItem.enabled = YES;
[self.locationManager startUpdatingLocation];
}
break;
case kCLAuthorizationStatusDenied:
NSLog(#"kCLAuthorizationStatusDenied");
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Anywall can’t access your current location.\n\nTo view nearby posts or create a post at your current location, turn on access for Anywall to your location in the Settings app under Location Services." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alertView show];
// Disable the post button.
self.navigationItem.rightBarButtonItem.enabled = NO;
}
break;
case kCLAuthorizationStatusNotDetermined:
{
NSLog(#"kCLAuthorizationStatusNotDetermined");
}
break;
case kCLAuthorizationStatusRestricted:
{
NSLog(#"kCLAuthorizationStatusRestricted");
}
break;
}
}
The code I am using here is from an old version of parse's Anywall Tutorial. I have tried adding in
case kCLAuthorizationStatusNotDetermined:
{
NSLog(#"kCLAuthorizationStatusNotDetermined");
[self.locationManager requestAlwaysAuthorization];
}
break;
In addition the application also displays the user's location on a map do I have to update that method as well?
You have to do it like this:
1)#import <CoreLocation/CoreLocation.h>
2)Set delegate CLLocationManagerDelegate
3)Create CLLocationManager *locationManager; Object
4)#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) in your .m file
5)Setup location manager
if (self.locationManager==nil) {
self.locationManager = [[CLLocationManager alloc]init];
}
self.locationManager.delegate = self;
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
// If the status is denied or only granted for when in use, display an alert
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusDenied || status == kCLAuthorizationStatusRestricted) {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0"))
{
NSString *title;
title = (status == kCLAuthorizationStatusDenied) ? #"Location services are off" : #"Background location is not enabled";
NSString *message = #"To use background location you must turn on 'Always' in the Location Services Settings";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Settings", nil];
[alertView setTag:1001];
[alertView show];
[alertView release];
}
else{
NSString *titles;
titles = #"Title";
NSString *msg = #"Location services are off. To use location services you must turn on 'Always' in the Location Services Settings from Click on 'Settings' > 'Privacy' > 'Location Services'. Enable the 'Location Services' ('ON')";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:titles
message:msg
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
}
// The user has not enabled any location services. Request background authorization.
else if (status == kCLAuthorizationStatusNotDetermined) {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0"))
{
[self.locationManager requestAlwaysAuthorization];
}
}
[self.locationManager startUpdatingLocation];
6)Setup alert view for iOS 8
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (alertView.tag==1001){
if (buttonIndex == 1) {
// Send the user to the Settings for this app
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}
}
}
Related
I use the following code to check and request authorization for the Camera. Problem is the following. The following scenario leads to a wrong authorization status:
User declines authorization for the first time
Terminates the app
Restarts the app
Leaves the application, grants authorization for the camera in settings app
Returns to the app
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] will return AVAuthorizationStatusDeclined (authorized as said).
After terminating and restarting results in AVAuthorizationStatusAuthorized as it should. In this case the user leaves to settings and denies camera access the result will remain AVAuthorizationStatusAuthorized until next restart.
Any ideas what I miss here?
- (void) popCamera {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
//picker.allowsEditing = YES;
#if !(TARGET_IPHONE_SIMULATOR)
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
#endif
self.view.translatesAutoresizingMaskIntoConstraints = YES;
[self presentViewController:picker animated:YES completion:NULL];
}
- (void)camDenied
{
NSLog(#"%#", #"Denied camera access");
NSString *alertText;
NSString *alertButton;
BOOL canOpenSettings = (&UIApplicationOpenSettingsURLString != NULL);
if (canOpenSettings)
{
alertText = LSS(#"DeniedCamera1");
SDCAlertView *alert = [[SDCAlertView alloc]
initWithTitle:LSS(#"DeniedCameraTitle")
message:alertText
delegate:self
cancelButtonTitle:LSS(#"Cancel")
otherButtonTitles:LSS(#"Goto"), nil];
alert.tag = 3491832;
[alert show];
}
else
{
alertText = LSS(#"DeniedCamera2");
SDCAlertView *alert = [[SDCAlertView alloc]
initWithTitle:LSS(#"DeniedCameraTitle")
message:alertText
delegate:self
cancelButtonTitle:LSS(#"Cancel")
otherButtonTitles:nil];
alert.tag = 3491832;
[alert show];
}
}
- (IBAction) onTakePhoto:(id)sender {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusAuthorized)
{
[self popCamera];
}
else if(authStatus == AVAuthorizationStatusNotDetermined)
{
NSLog(#"%#", #"Camera access not determined. Ask for permission.");
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted)
{
if(granted)
{
[self popCamera];
}
else
{
[self camDenied];
}
}];
}
else if (authStatus == AVAuthorizationStatusRestricted)
{
SDCAlertView *alert = [[SDCAlertView alloc]
initWithTitle:LSS(#"RestrictCameraTitle")
message:LSS(#"RestrictCamera")
delegate:self
cancelButtonTitle:LSS(#"OK")
otherButtonTitles:nil];
}
else
{
[self camDenied];
}
}
Credits for the original code: Is there a way to ask user for Camera access after they have already denied it on iOS 8?
This seems to be the intended behaviour. If Apple would want you to react to authorization changes at runtime, there would be a notification that tells you that it changed.
But right now, there is no such notification (as far as I can see). You just call +authorizationStatusForMediaType: and it either returns a definitive status (like denied or authorized), or it returns AVAuthorizationStatusNotDetermined to tell you that you need to request authorization via requestAccessForMediaType:completionHandler:.
Unfortunately, this isn't an authoritative answer; I'm just drawing conclusions and guessing here. You might want to ask on Apple's developer forum and hope to get an answer from an Apple engineer.
I've been looking around for ages to find a solution that will allow me to show my device location with Wi-Fi but not actually connected to any network. So it just has Wi-Fi turned on, however every method I've tried returns me with that I'm located in London. Does anyone know why this is happening?
Method i'm using
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
locationManager.distanceFilter = 1000;
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER) {
// Use one or the other, not both. Depending on what you put in info.plist
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
#endif
if ([self shouldFetchUserLocation])
{
[locationManager startUpdatingLocation];
}
// Do any additional setup after loading the view.
}
-(BOOL)shouldFetchUserLocation
{
BOOL shouldFetchLocation= NO;
if ([CLLocationManager locationServicesEnabled])
{
switch ([CLLocationManager authorizationStatus])
{
case kCLAuthorizationStatusAuthorized:
shouldFetchLocation= YES;
break;
case kCLAuthorizationStatusDenied:
{
UIAlertView *alert= [[UIAlertView alloc]initWithTitle:#"Error" message:#"App level settings has been denied" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
alert= nil;
}
break;
case kCLAuthorizationStatusNotDetermined:
{
UIAlertView *alert= [[UIAlertView alloc]initWithTitle:#"Error" message:#"The user is yet to provide the permission" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
alert= nil;
}
break;
case kCLAuthorizationStatusRestricted:
{
UIAlertView *alert= [[UIAlertView alloc]initWithTitle:#"Error" message:#"The app is recstricted from using location services." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
alert= nil;
}
break;
default:
break;
}
}
else{
UIAlertView *alert= [[UIAlertView alloc]initWithTitle:#"Error" message:#"The location services seems to be disabled from the settings." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
alert= nil;
}
return shouldFetchLocation;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
NSLog(#"location fetched in delegate");
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (fabs(howRecent) < 15.0) {
// If the event is recent, do something with it.
NSLog(#"inside loop.... latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
}
NSLog(#"latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
NSLog(#"\nlatitude: %+.6f \nlongitude: %+.6f", location.coordinate.latitude, location.coordinate.longitude);
[locationManager stopUpdatingLocation];
[locationManager stopMonitoringSignificantLocationChanges];
if(locationManager!=nil){
locationManager.delegate= nil;
locationManager= nil;
}
}
Output:
(Output without the bullet points)
location fetched in delegate
inside loop... latitude +51.509980, longitude -0.133700
latitude +51.509980, longitude -0.133700
latitude: +51.509980
longitude: -0.133700
You need to move this code:
[locationManager stopUpdatingLocation];
[locationManager stopMonitoringSignificantLocationChanges];
To another function that you call once your have a valid location returned. Right now you are only letting the locationManage update your location once, and this will most likely be a cached location (London?). It usually takes several calls to the didUpdateLocations delegate before a valid location is returned.
UPDATE:
Per OP's request... here is a little more info about location services based on the additional info provided by OP.
If your device does NOT have GPS AND you are not connected to a network (cell/WiFi) then what you are asking for is not possible. To receive location data, you need at least one of the following:
a GPS chip in your device
cell service CONNECTED to a network
WiFi service CONNECTED to a network
You cannot receive location data if at least one of the above conditions are not met. When a GPS chip is not present in the device, the network connection (Cell Tower/WiFi) is used to calculate your location instead. To do this the device determines location information based on the network it is connected to. This can be cell tower locations or know IP address locations and WiFi locations. This method is not as accurate as GPS but it is usually much quicker to return location data and uses less battery power.
I kept Guided Access for iPad app. When the app is launched it asks for user's current location using CLLocationManager.This is working under Normal mode and updates user current location. But under Guided Access, popup ("Allow to access your location") is not shown and authorizationStatus is always kCLAuthorizationStatusNotDetermined and doesn't update current location of user . Couldn't understand what could be the problem.Searched a lot but couldn't find it.
ViewController.m :
- (void)viewDidAppear:(BOOL)animated
{
[appDelegate startLocation];
[self performSelector:#selector(CheckLocationManger) withObject:nil afterDelay:0.1];
}
-(void)CheckLocationManger
{
AppAppDelegate *appDelegate=(AppAppDelegate*)[[UIApplication sharedApplication]delegate];
if(![CLLocationManager locationServicesEnabled])
{
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"Whoops we can’t find you!" message:#"Location services are disabled" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
if(activityIndictr)
[activityIndictr stopAnimating];
[alert1 show];
return;
}
if([CLLocationManager locationServicesEnabled])
{
if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied)
{
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"Whoops we can’t find you!"message:#"Location services are disabled. You can fix this by going to Settings > Privacy > Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
if(activityIndictr)
[activityIndictr stopAnimating];
[alert1 show];
return;
}
if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusNotDetermined) //This is called
{
[self performSelector:#selector(CheckLocationManger) withObject:self afterDelay:0.1];
return;
}
}
if(![self connected])
{
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"Network Error" message:#"Please verify that you have internet connectivity" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
if(activityIndictr)
[activityIndictr stopAnimating];
[alert1 show];
[alert1 release];
return;
}
else {
//continue further process
}
}
AppDelegate.m
- (void)startLocation
{
self.locationManager = [[[CLLocationManager alloc] init]autorelease];
self.locationManager.pausesLocationUpdatesAutomatically=NO;
[self.locationManager setDelegate:self];
if([[[UIDevice currentDevice ]systemVersion] floatValue]>=8.0)
{
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization]; //is executed but popup never displays
}
}
[self.locationManager startUpdatingLocation];
}
Any suggestions would be helpful.Thank you !
At very first set NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in your .plist.
Add CoreLocation.framework and import in your class.h file -> #import <CoreLocation/CoreLocation.h> then set CLLocationManagerDelegate to your class.
Declare #property (strong, nonatomic) CLLocationManager *locationManager;
Init locationManager and set default value to it.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[self.locationManager setDistanceFilter:200.0f];
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) // Or if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
[self.locationManager requestAlwaysAuthorization]; // Or [self.locationManager requestWhenInUseAuthorization];
[self.locationManager startUpdatingLocation];
Implement CLLocationMAnager delegate method
#pragma mark - Location Delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"updated coordinate are %#", [locations lastObject]);
CLLocation *currentLocation = [locations lastObject];
// Your code.....
}
Here I have 2 views:
LoginViewController
WallViewController
After user login in LoginViewController, it will go to WallViewController which contains a map view. First it will ask user permission to access current location. If user chooses to allow the access, there will not be any problem. However, if user chooses NOT to allow the access, user will be bounced from WallViewController back to LoginViewController. What I would like to do is to have user remain in WallViewController even though current location cannot be accessed. How can I achieve that? Here below is my relevant code.
LoginViewController.m
[PFUser logInWithUsernameInBackground:username password:password block:^(PFUser *user, NSError *error) {
// Tear down the activity view in all cases.
[activityView.activityIndicator stopAnimating];
[activityView removeFromSuperview];
if (user) {
//***************call WallViewController here*********
PAWWallViewController *wallViewController = [[PAWWallViewController alloc] initWithNibName:nil bundle:nil];
[(UINavigationController *)self.presentingViewController pushViewController:wallViewController animated:NO];
[self.presentingViewController dismissModalViewControllerAnimated:YES];
//****************************************************
} else {
// Didn't get a user.
NSLog(#"%s didn't get a user!", __PRETTY_FUNCTION__);
// Re-enable the done button if we're tossing them back into the form.
doneButton.enabled = [self shouldEnableDoneButton];
UIAlertView *alertView2 = nil;
if (error == nil) {
// the username or password is probably wrong.
NSLog(#"1");
alertView2 = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Couldn’t log in:\nThe username or password were wrong.", nil) message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Ok", nil), nil];
alertView2.tag = kSecondAlertViewTag;
} else {
// Something else went horribly wrong:
NSLog(#"2");
alertView2 = [[UIAlertView alloc] initWithTitle:[[error userInfo] objectForKey:#"error"] message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Ok", nil), nil];
alertView2.tag = kSecondAlertViewTag;
}
[alertView2 show];
// Bring the keyboard back up, because they'll probably need to change something.
[usernameField becomeFirstResponder];
}
}];
WallViewController.m
- (void)viewDidLoad {
// ...
[self startStandardUpdates];
}
- (void)startStandardUpdates {
if (nil == locationManager) {
locationManager = [[CLLocationManager alloc] init];
}
locationManager.delegate = self;
// This part was added due to a location authorization issue on iOS8
// See more at: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
if ([self._locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self._locationManager requestWhenInUseAuthorization];
}
self.mapView.showsUserLocation = YES;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Set a movement threshold for new events.
locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
CLLocation *currentLocation = locationManager.location;
if (currentLocation) {
PAWAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.currentLocation = currentLocation;
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
NSLog(#"%s", __PRETTY_FUNCTION__);
switch (status) {
case kCLAuthorizationStatusAuthorized:
NSLog(#"kCLAuthorizationStatusAuthorized");
// Re-enable the post button if it was disabled before.
self.navigationItem.rightBarButtonItem.enabled = YES;
[locationManager startUpdatingLocation];
break;
//**********This alert will show up, once click Ok it will go back to its caller which is LoginViewController***********
case kCLAuthorizationStatusDenied:
NSLog(#"kCLAuthorizationStatusDenied");
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"This app can’t access your current location.\n\nTo view nearby posts or create a post at your current location, turn on access for this app to your location in the Settings app under Location Services.", nil) message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Ok", nil), nil];
[alertView show];
// Disable the post button.
self.navigationItem.rightBarButtonItem.enabled = NO;
}
break;
//**********************************************************************************************************************
case kCLAuthorizationStatusNotDetermined:
NSLog(#"kCLAuthorizationStatusNotDetermined");
break;
case kCLAuthorizationStatusRestricted:
NSLog(#"kCLAuthorizationStatusRestricted");
break;
default:break;
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(#"%s", __PRETTY_FUNCTION__);
PAWAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.currentLocation = newLocation;
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
NSLog(#"%s", __PRETTY_FUNCTION__);
NSLog(#"Error: %#", [error description]);
if (error.code == kCLErrorDenied) {
[locationManager stopUpdatingLocation];
} else if (error.code == kCLErrorLocationUnknown) {
// todo: retry?
// set a timer for five seconds to cycle location, and if it fails again, bail and tell the user.
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error retrieving location", nil)
message:[error description]
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:NSLocalizedString(#"Ok", nil), nil];
[alert show];
}
}
Given the above code, what I found after login is that there will be a popup asking whether user allows current location access. If user chooses No, there will be an alert view saying "This app can’t access your current location. To view nearby posts or create a post at your current location, turn on access for this app to your location in the Settings app under Location Services." After I click Ok, it will go back to its caller which is LoginViewController but I want it to remain in WallViewController. Need some helps here. Thank you in advance.
I changed delegate:self to delegate:nil in the below code and it solved the issue.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"This app can’t access your current location.\n\nTo view nearby posts or create a post at your current location, turn on access for this app to your location in the Settings app under Location Services.", nil) message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(#"Ok", nil), nil];
When I launch my app I check current location authorisation status like this:
- (void)checkCurrentStatus
{
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)
{
[self.locationManager requestWhenInUseAuthorization];
}
else
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied && ![CLLocationManager locationServicesEnabled])
{
[self.locationManager startUpdatingLocation];
}
}
If overall location services are enabled (for the whole device) than it just asks user for permission, the alert pops up. If they are disabled (else if condition) then I need to call startUpdatingLocation because call to [self.locationManager requestWhenInUseAuthorization]; has no effect when authorisation status is kCLAuthorizationStatusDenied (without any if conditions). Ok, so I call startUpdatingLocation and then alert pops up which says:
Turn On Location Services to Allow "AppName" to Determine Your Location
Ok, I go to the settings on turn overall location services on. After that authorizationStatus becomes kCLAuthorizationStatusNotDetermined but when I call requestWhenInUseAuthorization it has no effect! No popup appears, user is not prompted for to authorise location, the status remains the same, I can't use location manager. How can I handle that?
From Apple's doc on CLLocationManager about - (void)requestWhenInUseAuthorization
If the current authorization status is anything other than
kCLAuthorizationStatusNotDetermined, this method does nothing and does
not call the locationManager:didChangeAuthorizationStatus: method
Here's what you need :
- (void)requestAlwaysAuthorization
{
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
// If the status is denied or only granted for when in use, display an alert
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusDenied) {
NSString *title;
title = (status == kCLAuthorizationStatusDenied) ? #"Location services are off" : #"Background location is not enabled";
NSString *message = #"To use background location you must turn on 'Always' in the Location Services Settings";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Settings", nil];
[alertView show];
}
// The user has not enabled any location services. Request background authorization.
else if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestAlwaysAuthorization];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
// Send the user to the Settings for this app
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}
}
Courtesy copy of this blog post