3
votes

I am using core locations to get the location of the iphone. I also implemented the delegate protocols to my viewcontroller files, and created a CLLocationmanager object..

When I press a button (IBAction), I want the location get updated. The delegate gets called correctly. I can see that because a NSLog messages appears with the lat/long coordinates.

But when I change the location in the IOS simulator and try to access the location again with the button, the location output I get remains the same. I have to push the button again to get the correct location. Obviously I want the location to be right the first time I push the button

This is my button that triggers the delegate:

- (IBAction)getLocation:(id)sender {


[locationManager startUpdatingLocation];
}

I have this piece of code in my viewDidLoad

locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;

This is my delegate method:

#pragma mark - CLLocationManagerDelegate 
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"didFailWithError: %@", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
                           initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
 }

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(@"didUpdateToLocation: %@", [locations lastObject]);
CLLocation *currentLocation = [locations lastObject];


if (currentLocation != nil) {
    _longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
    _latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
   }
[locationManager stopUpdatingLocation];
}

I'm running my code in Iphone 6.1 simulator..

6
Just a comment, in Objective C you can type if(currentLocation) instead of if (currentLocation != nil).The dude
It's because you only start updating location when you press the button, and stop once you get the first location (the first location may not be the most accurate). You should keep the locationManager updating location.danielbeard

6 Answers

4
votes

From the Apple Reference: CLLocationManager

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.

Also answered in another stack overflow post (https://stackguides.com/questions/12858548/cllocationmanager-holds-cache-value), use the timestamp property of CLLocation to filter out older cached location objects that are returned. I chose 15 seconds to be sure to differentiate a cached object but even only a few seconds will probably suffice:

NSTimeInterval timeInterval = [[location timestamp] timeIntervalSinceNow];
if (abs((NSInteger)timeInterval) < 15)
{
    //do something
}
1
votes

I figured it out, thanks to the comments below other answers..

I was waiting too short before calling the [locationManager stopUpdatingLocation]; method. The GPS just needed some more time..

So i just waited before doing the stopUpdatingLocation with an NSTimer. That did the job. Thanks to gWiz!

0
votes

I think , a different location has been setup as a mock location in your Xcode , that's what the simulator shows you. Check that out first. The simulator doesn't show you your current location , it shows the location that has been setup in Xcode as a mock location. Only device can show your real location. Hope it helps.

0
votes

This is probably because you are trying to update the UI from inside didUpdateLocations which most certainly runs on another thread than the main thread.

Change this:

if (currentLocation != nil) {
_longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
_latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
}

to this:

if (currentLocation != nil) {
    dispatch_async(dispatch_get_main_queue(), ^{
        _longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
        _latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
    });
}
0
votes

Try This Code in iOS6 Apple wants us to use didUpdateLocations instead of didUpdateToLocation

.h file


    CLLocationManager *locationManager;


.m File

  // get the current location latitude and longitude

    // locationManager update as location
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    [locationManager startUpdatingLocation];

    CLLocation *location = [locationManager location];


    locationManager.delegate=self;

    //Get user location
    [locationManager startUpdatingLocation];

    // Configure the new event with information from the location
    CLLocationCoordinate2D coordinate = [location coordinate];

    NSString *latitude = [NSString stringWithFormat:@"%f", coordinate.latitude];
    NSString *longitude = [NSString stringWithFormat:@"%f", coordinate.longitude];

    NSLog(@"dLatitude : %@", latitude);
    NSLog(@"dLongitude : %@",longitude);


- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation{

[locations lastObject];

}

0
votes

CLLocationManager does cache your location data. A useful approach would be to check the time interval between the updates. You will get a timestamp for each location updates. Compare the old and new location timestamps using this [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp] and discard those updates if interval is greater than 5 or so.