ScottOBot
ScottOBot

Reputation: 849

MKMapView and best way to zoom in on user's location

Hey so I have a map view that zooms in on the users location upon view load. Currently I find the users location using the CLLocationManager and initialize the map in the didUpdateLocations delegate method. However, as this is called multiple times I use a global BOOL that is set to true after the map is set once and then never set it again. Here is the code:

Define global BOOL and set it to false in the viewDidLoad:

@implementation MainMapViewController
{
    BOOL hasInitializedMap;
} 

- (void)viewDidLoad
{
    [super viewDidLoad];

    hasInitializedMap = NO;
}

I then get the user's location and set the maps zoom inside the (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations delegate method:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations lastObject];

    [self initializeMainMapView:location.coordinate.longitude latitude:location.coordinate.latitude];
}

- (void)initializeMainMapView:(float)longitude latitude:(float)latitude
{
    if (!hasInitializedMap)
    {
        CLLocationCoordinate2D zoomLocation;
        zoomLocation.latitude = latitude;
        zoomLocation.longitude = longitude;

        MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 1500, 1500);
        [mainMapView setRegion:viewRegion animated:YES];

        hasInitializedMap = YES;
    }
}

This code works but has left me wondering if there is a better way to do this. I hate using global flags like this as it can make your code confusing and is sloppy at best. Is there a better way to do what I am trying to do? Is there a delegate method that only gets called when the users position is updated for the first time? Can I do this with just the MKMapView and forget CoreLocation altogether?

Upvotes: 0

Views: 292

Answers (1)

Jake Hargus
Jake Hargus

Reputation: 362

I've done it a few ways... in fact the framework has been changed a few times so I can't remember how I settled on it. The MKMapkit does have a method for showing user location, developer doc:

This property does not indicate whether the user’s position is actually visible on the map, only whether the map view should try to display it. Setting this property to YES causes the map view to use the Core Location framework to find the current location and try to display it on the map. As long as this property is YES, the map view continues to track the user’s location and update it periodically. The default value of this property is NO.

Showing the user’s location does not guarantee that the location is visible on the map. The user might have scrolled the map to a different point, causing the current location to be offscreen. To determine whether the user’s current location is currently displayed on the map, use the userLocationVisible property.

The user's location will appear as an annotation. You can get the annotation and zoom in on that. what would be better would be to use that flag in conjunction with the MKMapViewDelegate which has a method -mapView:DidUpdateUserslocation:

delegate documentation

Maybe after you get the first one you can change the map's tracking mode to none (i'm not sure if that removes the user location annotation or not, if it does, you can easily drop a map pin there with the proper skin). -setUserTrakingMode:animated: is the method on MKMap can use for that.

One thing I would caution on, in writing apps that work with user location in the past, it take a few seconds to get an accurate location. You might want to let the GPS ping a few times first before you lock in on a position. I've found that the first few ticks can be wildly inaccurate. Hope that helps.

Upvotes: 1

Related Questions