Initial Zooming


#1

I found this little gem in some sample code -

[code]- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(@“didUpdateToLocation %@ from %@”, newLocation, oldLocation);

// Work around a bug in MapKit where user location is not initially zoomed to.
if (oldLocation == nil) {
	// Zoom to the current user location.
	MKCoordinateRegion userLocation = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 1500.0, 1500.0);
	[regionsMapView setRegion:userLocation animated:YES];
}

}[/code]

  • for anyone else who didn’t want the map to recenter every second or two. :wink:

#2

Good thing you found something about this bug !
However, it doesn’t seem to work in my case …

My method is as follows :

[code]- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(@“didUpdateToLocation %@ from %@”, newLocation, oldLocation);

// How many seconds ago was this new location created ?
NSTimeInterval t = [[newLocation timestamp] timeIntervalSinceNow];

// CLLocationManagers will return the last found location of the
// device first, you don't want that data in that case
// If this location was made more than 3 minutes ago, keep looking
if (t<-180) {
    // This is cached data, you don't want it, keep looking
    return;
}

// Work around a bug in MapKit where user location is not initially zoomed to.
if (oldLocation == nil) {
    [self foundLocation:newLocation];
}

}
[/code]

I added the if (oldLocation == nil) condition, and the newLocation is sent to the foundLocation method (so basically it’s the same as your sample code).
But it’s still centering the map every second, which is a bit annoying …

Did it solve your problem ?
Thanks
Fred


#3

The mapView generates userlocation updates even if your locationManager isn’t set to startUpdatingLocation. This means, every time the GPS on your device gets a fix, it sends a message to the mapView delegate that says there’s a new userLocation, which executes the function didUpdateUserLocation which executes the code to recenter and rezoom the map. To get out of this loop, you need to delete that method entirely, or set it so it only operates once.

The sample I posted doesn’t use the mapView delegate function didUpdateUserLocation, and expects you to tell the locationManager to startUpdatingLocation from the beginning. If you’re using the code from the book, though, most of the time you’ll wind up with an empty annotation pin on the map right away. This is probably because the locationManager updates the location so quickly when it starts up.

[code]- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(@"%@", newLocation);

// How many seconds ago was this new location created?
NSTimeInterval t = [[newLocation timestamp] timeIntervalSinceNow];

if (t < -180)
    return;

if (oldLocation == nil) {
    CLLocationCoordinate2D loc = [newLocation coordinate];
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 250, 250);
    [worldView setRegion:region animated:YES];
    [locationManager stopUpdatingLocation];
    return;
}

[self foundLocation:newLocation];

}[/code]

This is the code I used. I also deleted the mapView didUpdateUserLocation delegate function, and added

to the end of the initWithNibName: function, just after the setDesiredLocationAccuracy: method.

Unfortunately, to prevent the empty annotation from popping up at the start, you’ll have to write some extra coding in. As fas as know, the purpose of the chapter (in part) was really to demonstrate how delegation works, which here means passing off certain tasks and allowing or waiting for other parts of the code to handle them. If you really want to fix up the application so it doesn’t always rezoom or add an extra annotation on start up, you’ll need to rearrange the tasks in the code.

Best,
David

Edit:
Naturally, the minute after I post this I come up the simple solution:

if ([activityIndicator isAnimating]) [self foundLocation:newLocation];

:slight_smile: