0
votes

Below are some snippets of my code

BOOL checkingForLocation;
.
.
.
- (IBAction)LocationButtonTapped:(id)sender {
    [locationManager startUpdatingLocation];
    checkingForLocation = YES;
}
.
.
.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {

    [locationManager stopUpdatingLocation];
    // locationManager = nil;


    if (checkingForLocation) {
        checkingForLocation = NO;
        NSLog(@"here");
        // fetch data from server using location and present view controllers
    }
}

didUpdateLocations is called multiple times because locationManager is continually updating the location per startUpdatingLocation. My app has a bug where the code within if(checkingForLocation) runs multiple times and renders the view multiple times causing undesired results.

1) Why is it that stopUpdatingLocation doesn't stop further calls to didUpdateLocations?

2) Furthermore, if the checkingForLocation has already been set to NO why does the subsequent calls to didUpdateLocations still treat checkingForLocation as YES. Is there a race condition there?

Through searching other SO questions, I found that setting locationManager = nil will stop the extra calls to didUpdateLocations, which it does fix the issue in my case, but no real explanation. It seems that stopUpdatingLocation should take care of that. Any insight is much appreciated.

Thank you,

1
Where do you call [locationManager startUpdatingLocation]; checkingForLocation = YES;? - OgreSwamp
@OgreSwamp I call it when a button is pressed. I added the IBAction method above for clarity. - galenom

1 Answers

0
votes

didUpdateLocations: can be called frequently and at any time because of its async nature and optimisations :

Because it can take several seconds to return an initial location, the location manager typically delivers the previously cached location data immediately and then delivers more up-to-date location data as it becomes available. Therefore it is always a good idea to check the timestamp of any location object before taking any actions. If both location services are enabled simultaneously, they deliver events using the same set of delegate methods.

Actually, if you uncomment locationManager = nil; it should help, but if you want to use your checkingForLocation property, you should make the assignment synchronised. @synchronized(self) is the easiest way in this case.