I'm trying to learn how to use MKMapView and have created a sample application to do so; however, in my code I'm making a call to setRegion:animated to change the center point and the span, but the map never updates. I've run through a few threads on StackOverflow (SO) where others have mentioned similar problems and tried implementing their solutions to no avail.
Things I made sure to try in my code based on other's SO threads I found:
Ensure I initialized the MKMapView with a frame
Tried running the setRegion:animated method call on the main thread
My included my code below, can anyone shed some light on why my MKMapView instance will not update it's view?
EDIT: Correct code shown below:
MK_ViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MV_ViewController : UIViewController {
IBOutlet MKMapView *myMapView;
MKCoordinateRegion defaultRegion;
CLLocationCoordinate2D defaultCenter;
MKCoordinateSpan defaultSpan;
}
#end
MK_ViewController.m:
#import "MV_ViewController.h"
#interface MV_ViewController ()
#end
#implementation MV_ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// initialize default map view properties
defaultCenter = CLLocationCoordinate2DMake(33.732894,-118.091718);
defaultSpan = MKCoordinateSpanMake(0.028270, 0.0465364);
// Setup MapView's inital region
defaultRegion = MKCoordinateRegionMake(defaultCenter, defaultSpan);
// create the map view
CGRect screenRect = [[UIScreen mainScreen] bounds];
myMapView = [[MKMapView alloc] initWithFrame:screenRect];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// update map's initial view
[myMapView setRegion:defaultRegion animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
MK_ViewController+MKMapViewDelegate.m:
#import "MV_ViewController.h"
#implementation MV_ViewController (MKMapViewDelegate)
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
MKCoordinateRegion region = mapView.region;
CLLocationCoordinate2D center = region.center;
MKCoordinateSpan span = region.span;
NSLog(#"Center (lat,lon): (%f,%f)",center.latitude,center.longitude);
NSLog(#"Span (lat,lon): (%f,%f)",span.latitudeDelta,span.longitudeDelta);
}
#end
I solved the issue by removing the MKViewMap object from the NIB, and instead added it using the following code in the MK_ViewController.m file:
[self.view addSubView:myMapView];
The issue was that the NIB wasn't properly wired up to the view controller, and the view controller was creating it's own map view.
Thank you #Jason Cabot for pointing me in the right direction.
Related
I am making a simple app to display various things and on one of the tabs I like for it to display a map of your current location. It seems for some reason, even though in Xcode the controller is stretched towards the bottom, it looks like when run in the simulator, an area of unused space and I am unsure why.
I have the following code:
#interface MapViewController ()
#property (weak, nonatomic) IBOutlet MKMapView *map;
#end
#implementation MapViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_map.delegate = self;
_map.showsUserLocation = YES;
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
_map.centerCoordinate = userLocation.location.coordinate;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 200, 200);
[self.map setRegion:[self.map regionThatFits:region] animated:YES];
}
You need to add the constraints.
I have one problem. I've been looking at the other answers here on stack overflow about the same question and I can't get them to work for me. So I'm going to try asking here. What I want to do is when I'm on map view and have got the user location I want to automatically zoom into the location.
the h-file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface WalkingTableViewController: UIViewController <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *MKMapView;
#end
the m-file
#import "WalkingTableViewController.h"
#interface UITableViewController ()
#end
#implementation WalkingTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.MKMapView.showsUserLocation=YES;
self.MKMapView.delegate = self;
[self.MKMapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
}
- (IBAction)StopButton:(id)sender
- (IBAction)StartButton:(id)sender
#end
If you like to see the zoom animated, I would place the code in the viewDidAppear method, so that the animation starts once the view controller is displayed.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CLLocationManager* tempLocationManager = [[CLLocationManager alloc] init];
MKCoordinateRegion tRegion = MKCoordinateRegionMakeWithDistance([tempLocationManager.location coordinate], 20000, 20000);
[self.MKMapView setRegion:tRegion animated:animated];
}
Adjust the region (zoom level, 20000 in the example above) to your needs.
What you have to do is tell the mapview to zoom into a region. This should get you started:
CLLocationCoordinate2D center = _mapView.userLocation.coordinate;
MKCoordinateRegion region = MKCoordinateRegionMake(center, MKCoordinateSpanMake(2000, 2000));
[_mapView setRegion:region animated:YES];
I have written a simple method to utilize MKMapViewDelegate and I am having some trouble displaying the user location in the xcode 5 simulator. My understanding is that the code should be executed after a button from a previous view controller is pressed and the corresponding UIViewController class is created. However when the button is pressed and the View Controller with said map view is pushed onto the stack it simply displays the map with no zoom and no location. If I run the same code as a single view stand alone app it works just fine. What must I add or change to get the map to zoom to the users current location (in simulator its the San Fran headquarters) Here is the code I am using;
header:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface SPMenuViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *myMapView;
#end
implementation:
#import "SPMenuViewController.h"
#interface SPMenuViewController ()
#end
#implementation SPMenuViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.myMapView.delegate = self;
[self.myMapView setShowsUserLocation:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// Coords
CLLocationCoordinate2D myLocation = [userLocation coordinate];
// Zoom Region
MKCoordinateRegion zoomRegion = MKCoordinateRegionMakeWithDistance(myLocation, 2500, 2500);
// Show Location
[self.myMapView setRegion:zoomRegion animated:YES];
}
I think it should be noted that the previous view is Embedded in a Navigation Controller and a UIButton Class is connected by "push" segue to the View Controller containing the map view. Please help thank you!
If you set a breakpoint, is the userLocation value valid?
Setting showsUserLocation:YES should handle getting/displaying userLocation for you, but doesn't guarantee that the location will be on the map. Since you're setting the user location and zoomRegion in a delegate method, check when/if that method is actually called before the view appears. Could be it doesn't have an initial value to work with.
You could try setting the initial userLocation and zoomRegion in viewDidLoad instead of in didUpdateLocation to see if that works any better. This all looks like it should work ok.
Maybe a missing XCode setting to simulate location?
Current Location in the Simulator
ViewController.h
#import <UIKit/UIKit.h>
#import "MapKit/MapKit.h"
#interface ViewController : UIViewController <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//Setting Region
//MKCoordinateRegion *myRegion;
//Center
CLLocationCoordinate2D center;
center.longitude = 55.316667;
center.latitude = 25.266667;
//SPAN
MKCoordinateSpan span;
span.latitudeDelta = 0.30f;
span.longitudeDelta = 0.30f;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
As you see my code seems to be fine, and normally it should show the location given in latitude and longtitude values. But instead it shows this :
I am working in Xcode 5 with iOS 6.
Any ideas about the problem?
Nowhere in the code shown does it "give the coordinates to the map view" so why should it do anything?
All the code does is:
Declares local variables called center and span in the viewDidLoad method.
Sets the values of these local variables (which the map view knows nothing about).
The viewDidLoad method ends (doing nothing with the values of the local variables).
Adding this line after setting center and span actually gives the coordinates to the map view so that it shows those coordinates:
mapView.region = MKCoordinateRegionMake(center, span);
(Assuming, of course, that the mapView IBOutlet is connected to the MKMapView in the xib.)
Now, this will center the map view at the coordinates you specified and that's it.
If you were expecting any other effects (such as a pin appearing at the coordinates), you'll need to create an annotation with those coordinates and tell the map view to add it.
Trying to learn my way around MKMapView, but I've followed several tutorials and I can't seem to get it to zoom into my defined location, instead it just loads to a whole map view centered around the Atlantic ocean. I'm guessing something has changed in iOS6 that means the tutorials I am using no longer work? (The tutorials are iOS3-iOS5).
I've made a ViewController in Interface Builder, given it the custom class of MapViewController. I then dragged on MKMapView and using the Assistant Editor put this into MapViewController.h
MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController
#property (weak, nonatomic) IBOutlet MKMapView *myMapView;
#end
MapViewController.m
#import "MapViewController.h"
#define CLS_LATITUDE 54.85477
#define CLS_LONGITUDE -1.57371
#define SPAN 0.10f;
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize myMapView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
MKCoordinateRegion myRegion;
CLLocationCoordinate2D center;
center.latitude = CLS_LATITUDE;
center.longitude = CLS_LONGITUDE;
MKCoordinateSpan mySpan;
mySpan.latitudeDelta = SPAN;
mySpan.longitudeDelta = SPAN;
myRegion.center = center;
myRegion.span = mySpan;
[myMapView setRegion:myRegion animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The code for the region looks correct. Are you sure you have linked up the myMapView outlet in interface builder?
If you click and hold on the "File's Owner" object on the left, then hold Ctrl and drag from the File's Owner to the map view in the interface, when you let go of the mouse button you should get the option to set the outlet to myMapView. You can then see the link in the Connections inspector as shown on the right.
EDIT:
OK, so it appears that, as you are using Autolayout, the map view's frame has not been set by the time viewDidLoad gets called. I suggest you move it to - (void)viewWillLayoutSubviews. For example:
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[self setLocation];
}
-(void)setLocation {
// Set region etc...
}