IOS Waiting for launch of location manager

I am developing an iOS application based on map and location tracking. When the user first downloads the application, he requests permission to track location, etc. Just great. The only problem is that when I do this, I have code setting up the initial map view and other location-based variables before the user clicks OK.

I found that I can put these initialization steps after the while loop, which waits for the user to change the permissions of the location manager, as shown below, but this may not be best practice, not to mention that this leads to some strange behavior in transition between splash screen and map:

BOOL firstrun = TRUE; while ([[locationManager class] authorizationStatus] == kCLAuthorizationStatusDenied || [[locationManager class] authorizationStatus] == kCLAuthorizationStatusNotDetermined) { NSLog(@"Waiting for location permission"); } ...initiation code... 

Is there a listener available to access the location for the warning window or similar feature in the location manager delegate that I don't know about? I do not see such a method in the docs. Does anyone know what is best practice? Thank you very much.

EDIT I start location tracking as follows:

 if (nil == locationManager) locationManager = [[CLLocationManager alloc] init]; [locationManager startMonitoringSignificantLocationChanges]; self.musicmap.delegate = self; [self.mymap setShowsUserLocation:true]; 

thanks

+7
source share
3 answers

I would recommend making your CLLocationManagerDelegate class and then implement this method:

 - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { //Your code goes here } 

More information about CLLocationManagerDelegate can be found here .

Hope this helps!

+8
source

I had a similar problem with my application, and the application was doing something before the user managed to accept or decline the location resolution dialog. Here is what I did.

 -(BOOL)locationAuthorizationStatus { if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) { // user has not authorized us to use location UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Location Denied", @"Location Denied") message:NSLocalizedString(@"This app does not have permission to access your location. Please enable location access in device settings.", @"Message stating this app does not have permission to access your location and to enable location permission in settings") delegate:self cancelButtonTitle:NSLocalizedString(@"Ok", @"Ok") otherButtonTitles: nil]; [alert show]; return NO; } // Check if region monitoring is available for this device if (![CLLocationManager regionMonitoringAvailable]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Geofencing Unavailable", @"Geofencing Unavailable") message:NSLocalizedString(@"This device is not able to monitor regions", @"Message stating this device is not able to monitor regions") delegate:nil cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"Ok", @"Ok"), nil]; [alert show]; return NO; } else { if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) { // trigger a location check to prompt user for authorization LocationManagerController *locationController = [LocationManagerController sharedManager]; [locationController.locationManager startUpdatingLocation]; // the dialogue box is triggered here [locationController.locationManager stopUpdatingLocation]; _waitingOnAuthorization = YES; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkForAuthorizationStatusChange) name:@"WaitingOnAuthorizationStatus" object:nil]; return NO; } } return YES; } -(void)checkForAuthorizationStatusChange { if (_waitingOnAuthorization) { // this should only catch location change on first time if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) { // user approved location services } else { // user declined authorization } // set flag back to NO _waitingOnAuthorization = NO; } // remove our notification observer [[NSNotificationCenter defaultCenter] removeObserver:self]; } 

You will need to add variables that apply to your use case. But here is the gist of it.

  • Check authorization status using the BOOL method (locationAuthorizationStatus)
  • If you want to use the location, return YES, do whatever you want.
  • If not, returns NO and warns the user
  • If the location manager starts up for the first time to bring up the location dialog, then stop it to save the battery, sets a flag and sets a notification so that you know when the user hit yes or no.
  • The notification launches the checkAuthorizationChangeStatus method and resets the permissions to see what the user has done. From there, you can call any methods that you need, based on the choice of users.

Apple does not have any delegation methods to catch this choice, so the only way around it is through hacking. This method worked well for me. A bit hacked, but it works. Hope this helps.

+4
source
 //Start up motion manager, not sure if you need this for location manager motionManager = [[CMMotionManager alloc] init]; if (motionManager.accelerometerAvailable) { motionManager.accelerometerUpdateInterval = 1.0/2.0; [motionManager startAccelerometerUpdates]; } locationManager = [[CLLocationManager alloc] init]; //We will be the location manager delegate locationManager.delegate = self; //Track position at the 100m accuracy locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; //We want to see all location updates, regardless of distance change locationManager.distanceFilter = 0.0; [locationManager startUpdatingLocation]; 

Put the above somewhere in your "viewDidLoad" or appDelegate "didFinishLaunchingWithOption"

Listed below are updates and more. bestLocation is CLLocation. You will need to implement CLLocationManagerDelegate. TWO_MINUTES = 120

 - (BOOL)isBetterLocation:(CLLocation *)location { if (bestLocation == nil){ //best location not set yet, so it a better location by default return YES; } // Figure out how long it been since we got a better location NSTimeInterval timeDelta = [location.timestamp timeIntervalSinceDate:bestLocation.timestamp]; BOOL isSignificantlyNewer = timeDelta > TWO_MINUTES; BOOL isSignificantlyOlder = timeDelta < -TWO_MINUTES; BOOL isNewer = timeDelta > 0; if (isSignificantlyNewer) { return YES; }else if (isSignificantlyOlder) { return NO; } CLLocationAccuracy accuracyDelta = location.horizontalAccuracy - bestLocation.horizontalAccuracy; //You want accuracy to be low BOOL isLessAccurate = accuracyDelta > 0; BOOL isMoreAccurate = accuracyDelta < 0; BOOL isDifferent = location.coordinate.latitude != bestLocation.coordinate.latitude || location.coordinate.longitude != bestLocation.coordinate.longitude; if (isMoreAccurate) { return YES; } else if (isNewer && !isLessAccurate && isDifferent) { return YES; } return NO; } #pragma mark - Location manager delegate - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { if ([self isBetterLocation:newLocation]){ self.bestLocation = newLocation; } else { [locationManager stopUpdatingLocation]; isLocating = NO; NSLog(@"AppDelegate: Turning off location manager >>>>>>>>>>>>>>>>>>>>>"); } } 

Note. You do not need the "isBetterLocation" method. This will simply check the location and turn off the location manager after 2 minutes so that you do not wear out the user's battery. Sometimes you do not want the manager to disconnect, so you can leave it if you want.

I do not know how much of this you have already done. So I did it.

0
source

All Articles