objective-c MKMapView center on user location
Asked Answered
F

2

32

I'm trying to zoom into the user location as the center reference for the screen. I have this code:

MainViewController.h

#import <UIKit/UIKit.h>
#import "FlipsideViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

IBOutlet MKMapView *mapView;

@interface MainViewController : UIViewController <FlipsideViewControllerDelegate, MKMapViewDelegate> {
   MKMapView *mapView;
}
@property (nonatomic, retain) IBOutlet MKMapView *mapView;

MainViewController.m

@implementation MainViewController
@synthesize mapView;

 - (void)viewDidLoad {
    [super viewDidLoad];
    mapView = [[MKMapView alloc]
           initWithFrame:self.view.bounds
           ];
    mapView.showsUserLocation = YES;
    mapView.mapType = MKMapTypeHybrid;
    mapView.delegate = self;
    [self.view addSubview:mapView];
}

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
    MKCoordinateRegion region;
    MKCoordinateSpan span;
    span.latitudeDelta = 0.005;
    span.longitudeDelta = 0.005;
    CLLocationCoordinate2D location;
    location.latitude = userLocation.coordinate.latitude;
    location.longitude = userLocation.coordinate.longitude;
    region.span = span;
    region.center = location;
    [mapView setRegion:region animated:YES];
 }

Now I'm only getting a build warning on the last line [mapView setRegion:region animated:YES] stating: 'local declaration of 'mapView' hides instance variable'

Fortnightly answered 29/5, 2011 at 19:31 Comment(0)
G
72

When you do mapView.showsUserLocation = YES;, you ask it to retrieve the user location. This doesn't happen instantly. As it takes time, the map view notifies its delegate that a user location is available via the delegate method mapView:didUpdateUserLocation. So you should adopt the MKMapViewDelegate protocol and implement that method. You should move all your zooming-in code to this method.

Setting the delegate

- (void)viewDidLoad {
    [super viewDidLoad];
    mapView = [[MKMapView alloc]
           initWithFrame:CGRectMake(0, 
                                    0,
                                    self.view.bounds.size.width, 
                                    self.view.bounds.size.height)
           ];
    mapView.showsUserLocation = YES;
    mapView.mapType = MKMapTypeHybrid;
    mapView.delegate = self;
    [self.view addSubview:mapView];
}

Updated delegate method

- (void)mapView:(MKMapView *)aMapView didUpdateUserLocation:(MKUserLocation *)aUserLocation {
    MKCoordinateRegion region;
    MKCoordinateSpan span;
    span.latitudeDelta = 0.005;
    span.longitudeDelta = 0.005;
    CLLocationCoordinate2D location;
    location.latitude = aUserLocation.coordinate.latitude;
    location.longitude = aUserLocation.coordinate.longitude;
    region.span = span;
    region.center = location;
    [aMapView setRegion:region animated:YES];
}
Godliman answered 29/5, 2011 at 19:48 Comment(14)
I am extremely new to objective-c so bear with me...how I do call the didUpdateUserLocation method from within the didViewLoad method?Fortnightly
You don't. You adopt the protocol as @Srikar pointed out and as you seem to have done and then assign yourself as its delegate like mapView.delegate = self;. The map view will notify you on its own when it has the necessary information.Godliman
@Deepak @Srikar - please view my original post to see what is happening now after I updated things....Fortnightly
@Fortnightly Have you set the delegate?Godliman
@Deepak - you should how to set the delegate but where do I do that? I tried putting it in the viewDidLoad and in the DidUpdateUserLocation methods and I got a build error "MainViewController does not implement the MKMapViewDelegate protocol".Fortnightly
@Deepak - also, thats all I have in the console to show you - there is nothing elseFortnightly
@Deepak - like I said (check my OP for an update of the delete part also) I get an error "MainViewController does not implement the MKMapViewDelegate protocol" on this line.Fortnightly
Have you done this @interface MainViewController : UIViewController <FlipsideViewControllerDelegate, MKMapViewDelegate> like Srikar said?Godliman
And one final thing the delegate method is - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation and not the method shorthand mapView:didUpdateUserLocation:Godliman
@Deepak - my bad - I didn't put MKMapViewDelegate inside the @interface declaration - after doing this the zoom executes successfully. One last problem though is after implementing your last two suggestions I am now getting build warnings for location.longitute, location.latitude, and [mapView setRegion...] stating: 'location declaration of mapView hides instance variable' Do you know what this could be from?Fortnightly
yeah you have a property called userLocation and one of the arguments of the delegate method is also userLocation. Change the latter to aUserLocation. It should work.Godliman
I took the mapView off the front of mapView.userLocation.coordinate.latitude, etc. changing it to userLocation.coordinate.latitude and it fixed those two lines but I'm still receiving the error for [mapView setRegion:region animated:YES].Fortnightly
Which error are you getting? And can you update the question with your latest code?Godliman
Local variables are masking the instance variables. Adjusted the delegate method and edited it into my answer.Godliman
B
3

In your interface you forgot to inherit MapViewDelegate -

#import <MapKit/MapKit.h>

@interface MainViewController : UIViewController <FlipsideViewControllerDelegate, MKMapViewDelegate> 
{
   MKMapView *mapView;
}
@property (nonatomic, retain) IBOutlet MKMapView *mapView;

Rest seems fine.

Bovill answered 29/5, 2011 at 19:39 Comment(2)
I added your @property line and still am receiving the same problem errorFortnightly
I changed some stuff in my OP please check it againFortnightly

© 2022 - 2024 — McMap. All rights reserved.