Categories
Articles

XCode 4 IPhone Mountains of the USA Tutorial: Lesson 8 – Add MapView


<== Lesson 7 || Overview || Lesson 9 ==>

Now you have the second view added in the last lesson, you can add a map to show where the mountain is located. You can use the longitude and latitude that are part of the MountainItem data passed to the second view.

Detail View Screen with MapView

To work with a map, you need to include the MapKit framework. There are frameworks included automatically with a new IOS XCode project. They are UIKit, Foundation and CoreGraphics. You have probably noticed the import statement for UIKit in the header for MainViewController and DetailViewController.

In XCode 4 a group called Frameworks contains the frameworks you include with your project.

Typical Frameworks Group

It is a good practice to assure any new ones you add are in that group for easy reference.

Source Download

  1. Starting XCode 4 Project. This is the lesson 7 project completed.
  2. PHP and CSV Files. Script to read data file and selects by elevation and returns XML. See Lesson 2.
  3. Completed XCode 4 Project

[ad name=”Google Adsense”]

Step 1: Add the MapKit Framework
Download and uncompress the Starting XCode Project file and open in XCode.

In the project explorer select the top node.

Select Project Node

In the center of XCode follow these steps:

Steps to Open Frameworks and Libraries Dialog

Type map into the search text field and you should see the list narrow down to the MapKit.framework choice and then select the Add button.

Frameworks and Libraries Dialog

Locate the MapKit.framework file in the project explorer and drag it into the Frameworks group. You could leave MapKit.framework where it was grouped, but keeping the frameworks together makes sense.

Drag MapKit Framework To Frameworks Group

Step 2: DetailViewController.h – Replace TextView with MapView

Open the DetailViewController.h file in the project explorer.

You are going to replace the UITextView with a MKMapView. Lines that are being replaced are included here for convenience.

#import &amp;lt;UIKit/UIKit.h&amp;gt;
#import "MountainItem.h"

@interface DetailViewController : UIViewController {
    UITextView *mountainInfoTextView;

    MountainItem *mountainItem;
}
@property (nonatomic, retain) IBOutlet UITextView *mountainInfoTextView;

@property (nonatomic, retain) MountainItem *mountainItem;
@end

Line 2 below show the inclusion of MapKit in this class.

Lines 6 and 11 give you an IBOutlet to the MapView you add later to the DetailViewController.xib.

#import &amp;lt;UIKit/UIKit.h&amp;gt;
#import &amp;lt;MapKit/Mapkit.h&amp;gt;
#import "MountainItem.h"

@interface DetailViewController : UIViewController &amp;lt;MKMapViewDelegate&amp;gt;{
    MKMapView *mapView;

    MountainItem *mountainItem;
}

@property (nonatomic, retain) IBOutlet MKMapView *mapView;

@property (nonatomic, retain) MountainItem *mountainItem;

@end

Step 3: DetailViewController.m – Add mapView Property to the Implementation

Open the DetailViewController.m file in the project explorer.

These are the standard lines to include the mapView property to the implementation file.

You need to remove the mountainInfoTextView property and for convenience the lines are shown here.

#import "DetailViewController.h"

@implementation DetailViewController
@synthesize mountainInfoTextView;
@synthesize mountainItem;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)dealloc
{
    [mountainInfoTextView dealloc];
    [mountainItem dealloc];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.mountainInfoTextView = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

Include the lines below to add the mapView object.

#import "DetailViewController.h"

@implementation DetailViewController
@synthesize mapView;
@synthesize mountainItem;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)dealloc
{
    [mapView dealloc];
    [mountainItem dealloc];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.mapView = nil;

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

[ad name=”Google Adsense”]
Step 4: DetailViewController.m – Show the Mountain’s Location on the Map

Remove line 58 because you are replacing the mountainInfoTextView with the coding for the mapView.

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self setTitle:mountainItem.name];

    mountainInfoTextView.text = [NSString stringWithFormat: @"Name: %@\nElevation: %f\nLatitude: %f\nLongitude: %f",mountainItem.name, [mountainItem.elevation floatValue],  [mountainItem.latitude floatValue], [mountainItem.longitude floatValue]]; 

}
@end

Add the highlighted lines in the next code view.

The standard map type is set on line 59. You could also use MKMapTypeSatellite and MKMapTypeHybrid if you want to experiment.

Lines 60 and 61 are self explanatory.

The zoom and center point of the map is done on lines 62 to 67. Then center point is the longitude and latitude data passed into the class in the mountainItem object.

The span is an offset for the zoom. You can experiment with positive float numbers such as .01 which will zoom in tight. Because many of the mountains do not have any feature in standard map view, the value of 1 seems to show enough map details to keep from being disoriented.

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    [self setTitle:mountainItem.name];

    [mapView setMapType:MKMapTypeStandard];
    [mapView setZoomEnabled:YES];
    [mapView setScrollEnabled:YES];
    MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
    region.center.latitude = [mountainItem.latitude doubleValue] ;
    region.center.longitude = [mountainItem.longitude doubleValue] ;
    region.span.longitudeDelta = 1.0f;
    region.span.latitudeDelta = 1.0f;
    [mapView setRegion:region animated:YES];

}

@end

Step 5: DetailViewController.xib – Replace the TextView with the MapView

Open the DetailViewController.xib.

Delete the TextView in the design window.

Delete TextView

Drag the MapView from the Objects panel to the view in the design window and fill the view.

Drag MapView

With the MapView still selected open the Connections Inspector and drag a “New Referencing Outlet” to the File’s Owner and when you release the mouse select mapView, the name your are using in our DetailViewController to control the MapView. The Connections Inspector should look as follows:

Connections Inspector For MapView

Then finally as a double check select the File’s Owner and the Connections Inspector should appear as follows:

Connections Inspector for File’s Owner

You should be good to check this out in the Simulator. Remember you need to hold down the Option button and drag the mouse to get the multi touch over the map for zooming. Scroll the map by dragging the mouse.

<== Lesson 7 || Overview || Lesson 9 ==>