I have an app that will notify the user every time he approaches to one of my client's stores. There are more than 20 stores, so I have a function that takes the user's location and finds the 20 nearest stores to him and start monitoring the location of these stores, every time the user moves, the app finds the 20 nearest stores again, removes the previous stores from monitoring and start monitoring the new ones.
For some reason, it doesn't work, I'll be happy if one of you (or more :)) will help me to find the problem, Thanks!!
myCode (scroll to see the full code):
Note: the CLLocationManager created on the AppDelegate.m and it's delegate is this class (UIViewController).
-(void)sortClosestStores
{
[self.allStores sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
CLLocation *location1=[[CLLocation alloc] initWithLatitude:((Store*)obj1).geoPoint.latitude longitude:((Store*)obj1).geoPoint.longitude];
CLLocation *location2=[[CLLocation alloc] initWithLatitude:((Store*)obj2).geoPoint.latitude longitude:((Store*)obj2).geoPoint.longitude];
float dist1 =[location1 distanceFromLocation:self.locationManager.location];
float dist2 = [location2 distanceFromLocation:self.locationManager.location];
if (dist1 == dist2) {
return NSOrderedSame;
}
else if (dist1 < dist2) {
return NSOrderedAscending;
}
else {
return NSOrderedDescending;
}
}];
if (self.twentyClosestStores==nil) {
self.twentyClosestStores=[NSMutableArray array];
}
if (self.previousTwentyStores==nil) {
self.previousTwentyStores=[NSMutableArray array];
}
self.previousTwentyStores=self.twentyClosestStores;
self.twentyClosestStores=[NSMutableArray array];
for (int i = 0; i < 20; i++) {
[self.twentyClosestStores addObject:[self.allStores objectAtIndex:i]];
}
}
-(void)startMonitoringClosestStores
{
if (![CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
NSLog(#"Monitoring is not available for CLCircularRegion class");
}
for (Store *currentStore in self.twentyClosestStores) {
CLCircularRegion *region=[currentStore createCircularRegion];
[self.locationManager startMonitoringForRegion:region];
}
}
-(void)stopMonitoringStores
{
for (Store *currentStore in self.previousTwentyStores) {
CLCircularRegion *region=[currentStore createCircularRegion];
[self.locationManager stopMonitoringForRegion:region];
}
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
if (self.allStores!=nil) {
[self sortClosestStores];
[self stopMonitoringStores];
[self startMonitoringClosestStores];
}
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(#"Entered"); //Not called even when the user enters one of the regions.
}
Can you please help me? Thanks!
I'm pretty new at CoreLocation myself but I would think that it is not a good idea to call stopMonitoringForRegions and startMonitoringForRegions in didUpdateLocations.
Since you're monitoring regions, the didEnterRegion delegate is what you will be interested in. That will give you the 'hey, I arrived at the X store' event, and in there is where you would probably want to call the code that you currently have in your didUpdateLocations.
You will want to setup CoreLocation probably in your AppDelegate, so you might have something like (sorry about it being Swift, that's what I'm working in right now):
locationManager.delegate = self
// auths:
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
// config:
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = true
locationManager.allowsBackgroundLocationUpdates = true
locationManager.activityType = CLActivityType.AutomotiveNavigation
// start:
locationManager.startMonitoringSignificantLocationChanges()
Then you would have your code:
if (self.allStores!=nil) {
[self sortClosestStores];
[self stopMonitoringStores];
[self startMonitoringClosestStores];
}
Note: I don't think it matters if you call startMonitoringSignificantLocationChanges before or after adding monitored regions, I haven't gotten quite that far in my code yet.
didUpdateLocations is more for when you want to track location e.g. tracking a bicycle ride or jogging session.
Additional explanation:
OK, I think I understand the issue now. There are two aspects to what you want to accomplish:
being notified when the user enters a store's region
dynamically recalculating the nearest N stores as the device moves
My previous answer was geared towards the first issue.
Regarding the second issue, dynamically recalulating nearest N, the code in your didUpdateLocations will not be called unless you tell the location manager to startUpdatingLocation. Just off the top of my head:
// configure the location manager in AppDelegate:
// You will need to experiment with these two properties,
// you probably don't want to use kCLLocationAccuracyBestForNavigation.
// Maybe kCLLocationAccuracyKilometer would be sufficient.
locmgr.distanceFilter = n
locmgr.desiredAccuracy = m
locmgr.pausesLocationUpdatesAutomatically = true
locmgr.startUpdatingLocation()
// this is the delegate that will receive the events due to locmgr.startUpdatingLocation
locationManager:didUpdateLocation {
// Unless you have a specific need for it, I would refactor so that
// you don't need self.PreviousTwentyStores:
[self stopMonitoringStores];
[self sortClosestStores];
[self startMonitoringClosestStores];
}
locationManager:didEnterRegion {
// you are in the region surrounding one of the stores.
}
Alternately, consider just setting a timer and waking the app every N seconds or minutes to recalculate the nearest stores.
As I understand the various aspects of CoreLocation
startUpdatingLocation -> didUpdateLocations -> stopUpdatingLocation
is (in one sense) entirely separate from:
startMonitoringForRegion -> didEnterRegion | didExitRegion -> stopMonitoringForRegion
Additionally, startUpdatingLocation was never called so your didUpdateLocation was never called.
Related
I have a location app that needs to get accurate location periodically. Currently I am getting constantly getting location in didUpdateLocation but I only ever log the location every 5 seconds. I am interested in a solution that gets accurate location periodically or on signification change. I would like either or both of these scenarios:
(by very accurate, I need 10m of desired accuracy)
Get a very accurate location every 5 seconds
Notify/callback if user moves a threshold ( eg moves 5 - 10 meters)
The app needs to work when backgrounded as well and location must still be logged if user switches to another app.
I was considering turning on/off location every 5 seconds but was not sure if that is the best practice. I also know there is also allowDeferredLocationUpdatesUntilTraveled but I believe that only applied to backgrounded mode. I would appreciate a solution that saves battery when the app is in use and in background mode. Please share your solutions and best practices for my use case.
I did write an app using Location services, app must send location every 10s. And it worked very well.
Just use the "allowDeferredLocationUpdatesUntilTraveled:timeout" method, following Apple's doc.
Steps are as follows:
Required: Register background mode for update Location.
Create LocationManger and startUpdatingLocation, with accuracy and filteredDistance as whatever you want:
-(void) initLocationManager
{
// Create the manager object
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
_locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
_locationManager.desiredAccuracy = 45;
_locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[_locationManager startUpdatingLocation];
}
To keep app run forever using "allowDeferredLocationUpdatesUntilTraveled:timeout" method in background, you must restart updatingLocation with new parameter when app moves to background, like this:
- (void)applicationWillResignActive:(UIApplication *)application {
_isBackgroundMode = YES;
[_locationManager stopUpdatingLocation];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[_locationManager startUpdatingLocation];
}
App gets updatedLocations as normal with "locationManager:didUpdateLocations:" callback:
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// store data
CLLocation *newLocation = [locations lastObject];
self.userLocation = newLocation;
//tell the centralManager that you want to deferred this updatedLocation
if (_isBackgroundMode && !_deferringUpdates)
{
_deferringUpdates = YES;
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
}
}
But you should handle the data in then "locationManager:didFinishDeferredUpdatesWithError:" callback for your purpose
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
_deferringUpdates = NO;
//do something
}
NOTE: I think we should reset parameters of LocationManager each time app switches between background/forgeround mode.
Hopefully this should help
I've implemented in my app the region monitoring feature of CLLocationManager, it works but it kills my battery:
-
-
Is it should be like that?
My code:
monitorLocationViewController.m (please scroll to see the full code):
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//If "allStores"(NSMutableArray) isn't nil - calling "locationChangeHandler" to update monitoring
if (self.allStores!=nil) {
[self locationChangeHandler];
}
CLLocation *currentLocation=(CLLocation*)[locations lastObject];
NSSet *monitoredRegionsSet=self.locationManager.monitoredRegions;
[monitoredRegionsSet enumerateObjectsUsingBlock:^(CLCircularRegion *region, BOOL *stop) {
if ([region containsCoordinate:currentLocation.coordinate]) {
[self.locationManager stopMonitoringForRegion:region];
[self locationManager:self.locationManager didEnterRegion:region];
}
}];
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
Store *store=[self storeForRegion:region];
if (store.alreadySendNotification==NO) {
UILocalNotification *notification=[[UILocalNotification alloc] init];
notification.alertTitle=#"Arounder";
notification.alertBody=[[self storeForRegion:region] address];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
store.alreadySendNotification=YES;
}
}
//For updating monitoring
-(void)locationChangeHandler
{
//If "allStores"(NSMutableArray) isn't nil
if (self.allStores!=nil) {
//Finding the 20 closest stores to he user's location and adding it to "twentyClosestStores"(NSMutableArray)
[self sortClosestStores];
//Stop monitoring "previousTwentyStores"(NSMutableArray) (20 closest stores before user's location updated)
[self stopMonitoringStores];
//Start monitoring "twentyClosestStores"(NSMutableArray)
[self startMonitoringClosestStores];
}
}
//Start monitoring "twentyClosestStores"(NSMutableArray)
-(void)startMonitoringClosestStores
{
//If monitoring isn't availible for "CLCircularRegion"
if (![CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
NSLog(#"Monitoring is not available for CLCircularRegion class");
return;
}
//Run on all "twentyClosestStores"(NSMutableArray)'s objects
for (Store *currentStore in self.twentyClosestStores) {
//Start monitoring "region"(CLCircularRegion)
[self.locationManager startMonitoringForRegion:currentStore.circularRegion];
}
}
//Stop monitoring "previousTwentyStores"(NSMutableArray) (20 closest stores before user's location updated)
-(void)stopMonitoringStores
{
//Run on all "monitoredRegions"(NSSet) of "locationManager"(CLLocationManager) objects
for (CLCircularRegion *currentRegion in self.locationManager.monitoredRegions) {
//Stop monitoring "region"(CLCircularRegion)
[self.locationManager stopMonitoringForRegion:currentRegion];
}
}
//Finding a store for region
-(Store*)storeForRegion:(CLCircularRegion*)region
{
//Run on all "allStores"(NSMutableArray)'s objects
for (Store *currentStore in self.allStores) {
//If "currentStore"(Store)'s "circularRegion"'s identifier is equal to "region"(CLCircularRegion)'s identifier
if ([currentStore.circularRegion.identifier isEqualToString:region.identifier]) {
//Returning "currentStore"(Store)
return currentStore;
}
}
//Store not found - returning nil
NSLog(#"No store found for this region: %f,%f",region.center.latitude,region.center.longitude);
return nil;
}
AppDelegate.m:
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.monitorLocationVC=[[monitorLocationViewController alloc] init];
self.monitorLocationVC.locationManager=self.locationManager;
[self configureLocationManager];
[self.locationManager startUpdatingLocation];
return YES;
}
-(void)configureLocationManager
{
//Initializing locationManager
self.locationManager=[[CLLocationManager alloc] init];
//setting "locationManager"'s(CLLocationManager) delegate to "self"
self.locationManager.delegate=self.monitorLocationVC;
//Setting "locationManager"'s(CLLocationManager)'s distance filter to none
self.locationManager.distanceFilter=kCLDistanceFilterNone;
//Setting "locationManager"'s(CLLocationManager)'s activityType to navigation
self.locationManager.activityType=CLActivityTypeAutomotiveNavigation;
//setting "locationManager"'s(CLLocationManager) desiredAccuracy to "best"
self.locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
self.locationManager.pausesLocationUpdatesAutomatically=NO;
//If OS version is 9 or above - setting "allowsBackgroundLocationUpdates" to YES
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
}
Thank you!
You only want to monitor regions, not update their location constantly in the background.
Try this:
self.locationManager.desiredAccuracy=kCLLocationAccuracyBest;
Do you really need the distanceFilter set to kCLDistanceFilterNone? That will cause more battery power to be used. You probably want to try to set that to around 10, 20, 50 or even 100 meters.
Also, in order to not update locations constantly, instead of:
[self.locationManager startUpdatingLocation];
Try just using:
[self.locationManager startMonitoringSignificantLocationChanges];
All of these things should contribute to less battery usage. When you set accuracy and distance filters to the highest possible setting, the battery is going to be drained.
EDIT:
You are going to eat up a lot of battery whatever you do because of the purpose of your app. A solution I've done before with a problem similar to this is to create algorithm or formula with an NSTimer that fires every x minutes to update the user's location. (but only update regions if they have moved x meters).
stop location updates between firing of the NSTimer so that you aren't constantly updating locations.
when the timer fires, resume location updates, grab about 10 locations (so you get an accurate one), then shut off location updates until the next time the timer is fired
I'm getting my location position from the iPhone's GPS. I want to get the coordinate from the same point 15 times (to get the best horizontal accuracy).
Is there a way to wait for example, 2 seconds between one coordinate and another?
I use an object called coordinate, with latitude and longitude as property.
.... Exemple code
Coordinate * coord = [[Coordinate alloc] init];
NSMutableArray *coordinates = [[NSMutableArray alloc] init];
for (i=0 ; i<=14; i++)
{
coord = newlocation;
[coordinates addObject:coord];
.... some code to wait 2 seconds before add a new object to the array....
}
I tried to use NSThread sleepfortimeinterval, but the view freezes.
Thanks
Rather than having a for loop like this, you could theoretically use a repeating NSTimer that fired every two seconds, and then invalidate the timer after 15 iterations.
But I'd not suggest doing that, but rather shift to an event-driven model, waiting for calls to your didUpdateLocations. There's no point in checking in two seconds, if didUpdateLocations hasn't been updated. Likewise, there's no point in repeatedly checking 15 times over 30 seconds if, for example, you get a really accurate location after 5 seconds.
I'd suggest start monitoring the location, watch the locations as they come in with subsequent calls to didUpdateLocations, and examine horizontalAccuracy of the CLLocation (which tells you how accurate the location is). Once you reach the desired horizontalAccuracy, you can declare success (e.g. stop monitoring locations or whatever). You could also establish a NSTimer that automatically turned off the monitoring of locations after 30 seconds, if you want, as well.
For example:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%s", __PRETTY_FUNCTION__);
[self startStandardUpdates];
// after 30 seconds, if we haven't found a location, declare success with whatever we got (if anything)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self stopStandardUpdates]; // stop monitoring location if you want
if (!self.foundLocation) {
if (self.bestLocation) {
NSLog(#"Didn't find perfect location, but location has accuracy of %.1f meters", self.bestLocation.horizontalAccuracy);
} else {
NSLog(#"Even after 30 seconds, did not find any locations!");
}
}
});
}
#pragma mark - Location Services
- (void)startStandardUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == self.locationManager)
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Set a movement threshold for new events.
self.locationManager.distanceFilter = 5;
[self.locationManager startUpdatingLocation];
}
- (void)stopStandardUpdates
{
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation* location = [locations lastObject];
NSLog(#"%s: horizontalAccuracy = %.1f", __FUNCTION__, location.horizontalAccuracy);
if (location.horizontalAccuracy < 0) // not a valid location
return;
// this checks to see if the location is more accurate than the last;
// or you might just want to eliminate this `if` clause, because if
// you get updated location, you can probably assume it's better than
// the last one (esp if the user might be moving)
if (!self.bestLocation || location.horizontalAccuracy <= self.bestLocation.horizontalAccuracy) {
self.bestLocation = location;
}
if (location.horizontalAccuracy <= 5) { // use whatever you want here
NSLog(#"Found location %#", location);
self.foundLocation = YES;
[self stopStandardUpdates]; // stop it if you want
}
}
This uses the following properties:
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLLocation *bestLocation;
#property (nonatomic) BOOL foundLocation;
Hi I am implementing Location services in my app. First I have to know my Coordinates to get the distance between some places that I have in a list and the device. Then if I go into a place I can make a check in, so, I need to get coordinates again, and the problem is here. Second time I try to get coordinates, the method -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations is not called.. and I can not get new Coordinates.
My manager is located in a NSObject sublcass with this code:
(id)init {
if ( self = [super init] ) {
if ([CLLocationManager locationServicesEnabled])
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
}
return self;
}
-(void) checkLongLatitudeAgain {
[locationManager startUpdatingLocation];
}
#pragma mark Delegates de CLLocationManager
//
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"LON%f", manager.location.coordinate.longitude);
NSLog(#"LAT:%f", manager.location.coordinate.latitude);
NSTimeInterval howRecentNewLocation = [newLocationeventDate timeIntervalSinceNow];
if (manager.location.horizontalAccuracy <= 100.0 && howRecentNewLocation < -0.0 && howRecentNewLocation > -20.0){
//Usar coordenada
[self.delegate getLocationForCheckIn:manager.location];
[self stopUpdatingLocation:#"Fins"];
}
}
// ---------------------------------------------------------------------------------------------------------------------
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
//
if ([error code] != kCLErrorLocationUnknown) {
[self stopUpdatingLocation:NSLocalizedString(#"Error", #"Error")];
}
//
}
// ---------------------------------------------------------------------------------------------------------------------
- (void)stopUpdatingLocation:(NSString *)state {
//Detenemos la lectura del GPS
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
NSLog(#"Stop gps");
//
}
I call the class when the list of places is open, and also when inside a place the user press checkIn button. Both times I do it with this code:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
You are creating a new manager every time:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
That new manager is not assigned to any delegate.
You need to use the previous manager you have created and assigned to your delegate, something like:
[locationManager checkLongLatitudeAgain];
You can check the documentation at http://developer.apple.com - https://developer.apple.com/library/ios/documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html
In particular you can check the Starting the Standard Location Service and Starting the Significant-Change Location Service sections. You have to use the startMonitoringSignificantLocationChanges or startUpdatingLocation method of CLLocationManager, cache your location somewhere and update it only when a new location is received, otherwise like it is stated in the documentation: "If a location update has already been delivered, you can also get the most recent location data directly from the CLLocationManager object without waiting for a new event to be delivered".
i dont know why you are initiating your location manager again again, also even if you some how manage to solve current problem but it's not proper way of dealing with location manage based applications.I had been in trouble previously when i was working on location based app. the best approach for location based app is singleton.
apple forum discussion
you can find
this
and this very helpful.
just an advice, :)
Thanks.
In iOS8 for me I had to call [locationManager stopUpdatingLocation]; before calling [locationManager startUpdatingLocation] to start getting updates second time and it works for me.
I am using the Core Location framework to locate the device and once locationManager:didUpdateToLocation:fromLocation: method is called with a location, I stop tracking the user.
However the first time I launch the app (from a fresh install). When I message startUpdatingLocation of my Location Manager, the user gets the alert to accept or refuse location service.
When I accept the tracking doesn't begin, it's only when I go away and come back to this view controller when startUpdatingLocation is again called that notifications start coming in.
I am implementing locationManager:didChangeAuthorizationStatus: thinking that this would get messaged when the user accepts (or refuses) location services, but it doesn't.
Can anyone point me in the right direction for updating location as soon as the location services message has been dismissed ?
Thanks.
UPDATE WITH CODE SAMPLE
I've got a singleton class which encapsulates my logic, the idea is when the user location is requested, a check on the CLLocation's timestamp is performed and if it's too old, start tracking is messaged, which lazy loads my CLLocationManager iVar,
-(void)startTracking{
if(!self.locationManager)
_locationManager = [[CLLocationManager alloc] init];
if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied){
[self invalidateUserLocation];
}else{
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
}
}
New location received:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
_userLocation = [newLocation retain];
NSDictionary * info = [NSDictionary dictionaryWithObject:self.userLocation
forKey:#"userLocation"];
[[NSNotificationCenter defaultCenter] postNotificationName:kUserLocationFound
object:self
userInfo:info];
[self stopTracking];
}
Stop tracking:
-(void)stopTracking{
if(!self.locationManager)
return;
[self.locationManager stopUpdatingLocation];
self.locationManager.delegate = nil;
}
When I have a view controller which needs the users location I call userLocation on my singleton object like so. If it's recent, I return the CLLocation, otherwise I return nil and start again. Notice I stop tracking when I receive the first update. But the first time this runs and I get the alert view, nothing is tracked at all.
- (CLLocation*)userLocation
{
if(_userLocation.coordinate.latitude == 0 && _userLocation.coordinate.longitude == 0){
[self startTracking];
return nil;
}else{
NSDate* timeNow = [NSDate date];
NSTimeInterval interval = [timeNow timeIntervalSinceDate:_userLocation.timestamp];
if(interval >10)
[self startTracking];
return _userLocation;
}
}
Did you try calling – locationManager:didChangeAuthorizationStatus: from CLLocationManagerDelegate?
I'm going to guess that you call startTracking when the view controller loads. This is circumvented by the alert which ask for if it's okay. At that point, the start locating message won't be called again so by calling didChangeAuthorizationStatus, you can call your startTracking method.
Something like:
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusDenied) {
//location denied, handle accordingly
}
else if (status == kCLAuthorizationStatusAuthorized) {
//hooray! begin startTracking
}
}
If that's not the case, let me know.