iPhone Maps App Tutorial Part # 1 – create an app to display a map

This will be a multipart tutorial on the MKMapView. In this part we will create a simple app to display the map.

1.) Create a new View-based application in Xcode, name it MapTutorial.

2.) Right click on Frameworks under the Groups & Files section in XCode. Select Add > Existing Frameworks. Select MapKit.framework and click Add.

Add existing framework

Add MapKit.framework
3.) Open MapTutorialViewController.h and add the following code. We imported our MapKit.h from the MapKit framework we added in step 1. We also added an MKMapView variable.

#import 
#import 

@interface MapTutorialViewController : UIViewController 
{
	
	IBOutlet MKMapView	*mapView;
	
}

@end

4.) Expand the Resources folder and double click MapTutorialViewController.xib to open it up in Interface Builder. Drag a Map View from the Library onto the view window.
Library

View Window

5.) While we’re still in Interface Builder select File’s Owner in the document window and then go to the Connections Inspector and connect the mapView outlet to the MKMapView in our view window.
Connections Inspector

Then in the document window expand View and you should see Map View.

document window

Control click on Map View and drag to File’s Owner, select delegate.

select delegate

You can then save everything and close Interface Builder.

6.) If you click Build & Run in Xcode now, you’ll see something like this.

simulator shot

Not real exciting and probably not what we’re looking for. Let’s change that.

7.) Open Up MapTutorialViewController.h and add an internal interface named AddressAnnotation. And add a reference to AddressAnnotation. Then add a method declaration for showAddress.

#import 
#import 

@interface AddressAnnotation : NSObject  
{
	CLLocationCoordinate2D coordinate;
	
	NSString *title;
	NSString *subTitle;
}

@end

@interface MapTutorialViewController : UIViewController 
{
	
	IBOutlet MKMapView	*mapView;
	
	AddressAnnotation *addAnnotation;

}

- (IBAction) showAddress;

@end

8.) Open up MapViewController.m and add the implementation for AddressAnnotation

#import "MapTutorialViewController.h"

@implementation AddressAnnotation

@synthesize coordinate;

- (NSString *)subtitle
{
	return @"Sub Title";
}
- (NSString *)title
{
	return @"Title";
}

-(id)initWithCoordinate:(CLLocationCoordinate2D) c
{
	coordinate=c;
	NSLog(@"%f,%f",c.latitude,c.longitude);
	return self;
}

@end


@implementation MapTutorialViewController

- (void)viewDidLoad 
{
    [super viewDidLoad];
}



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

@end

9.) Then add the showAddress method to the MapTutorialViewController implementation. I added it right after the viewDidLoad method in my code.

- (IBAction) showAddress 
{
	
	MKCoordinateRegion region;
	MKCoordinateSpan span;
	span.latitudeDelta=0.2;
	span.longitudeDelta=0.2;
	
	CLLocationCoordinate2D location = mapView.userLocation.coordinate;
	
	location.latitude = 38.898748 ;
	location.longitude = -77.037684;
	region.span=span;
	region.center=location;
	
	if(addAnnotation != nil) 
	{
		[mapView removeAnnotation:addAnnotation];
		[addAnnotation release];
		addAnnotation = nil;
	}
	
	addAnnotation = [[AddressAnnotation alloc] initWithCoordinate:location];
	[mapView addAnnotation:addAnnotation];
	
	[mapView setRegion:region animated:TRUE];
	[mapView regionThatFits:region];
	//[mapView selectAnnotation:mLodgeAnnotation animated:YES];
}

10.) We also need to add the mapView:viewForAnnotation method. I put this right after the showAddress method.

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id ) annotation
{
	MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"currentloc"];
	annView.pinColor = MKPinAnnotationColorGreen;
	annView.animatesDrop=TRUE;
	annView.canShowCallout = YES;
	annView.calloutOffset = CGPointMake(-5, 5);
	return annView;
}

11.) We’re going to call showAddress from the viewDidLoad method.

- (void)viewDidLoad 
{
    [super viewDidLoad];
	[self showAddress];
}

12.) Save everything and click Build and Run. You should see a map similar to this.

simulator shot

That’s it for part 1. We created an app to show a point on a map. You can try other points including your own address. Just plug your address into a site that will convert it to Longitude and Latitude. Here’s the one I used http://geocoder.us/. Once you have the coordinates, plug them into the show address method in the location.latitude and location.longitude variables and the map will center on your address.

In part 2 we’ll expand on this a little bit.
Here’s the code.



This entry was posted in MapView and tagged , , , , , , . Bookmark the permalink.

23 Responses to iPhone Maps App Tutorial Part # 1 – create an app to display a map

  1. Good first half tutorial buddy!

    It says it was posted March 6th, 2011? Seems to be using an older SDK version though. Have you considered updating?

    Anyway, Thanks for the help!

    (p.s. your ViewForAnnotation code extract image is very stretched: Just an FYI).

    Keep it going! :)

    • Sorry, I have no idea where I got the impression you were using an older version of the SDK – For some reason I automatically saw the 3Gs simulator rather than the iPhone 4! Excuse my stupid mistake!

      Anyway, now followed the second part of the tutorial! Very well set out and simple to follow – especially like the highlighted code where changed between extracts!

      Good work!

  2. Kent says:

    You can always click the code images to open them in a new window at 100%.

    Thanks for the kind words.

  3. Gere Tan says:

    Hello, I am new with Iphone Xcode, I have one question:

    if i store the latitude & longitude number on the plist.

    For example:
    latitude = 38.89;
    longitude = -77;

    How to read it from plist and apply to your above code.

    Thanks!!

    • Kent says:

      Try taking a look at this tutorial and see if it’s any help.
      http://www.theappcodeblog.com/?p=524

      If not I’ll post some code for you next week, when I’m back from vacation.

      • Gere Tan says:

        http://www.theappcodeblog.com/?p=524

        Sorry, I follow this guide still can’t success. The result which I run on the console always show null or 0.00000.

        I used below code for reading the plist:
        NSBundle *bundle = [NSBundle mainBundle];
        NSString *plistPath = [bundle pathForResource:@"data" ofType:@"plist"];
        NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile: plistPath];
        NSArray *coordinateArray = [[NSArray alloc] initWithArray:[dictionary objectForKey:@"Root"]];

        lat = [coordinateArray valueForKey:@"latitude"];
        lon = [coordinateArray valueForKey:@"longitude"];

        NSLog (@”%”, lat);

        My plist’s format as below:

        restaurant
        AAA
        address
        XXXXXXXXXXXXXX
        images
        XXXX.png
        tel
        0225062255
        businesshour

        offday
        none
        website

        description

        latitude
        25.265
        logitude
        121.214

        restaurant
        BBB
        address
        BBBBBBBBBBBBBBBB
        images
        BBB.png
        tel
        0422200012
        businesshour

        offday
        none
        website

        description

        • Kent says:

          I didn’t want to try and re-create your Plist so I created my own with just two values, String Latitude = 38.89 and String Longitude = -77.

          I used this code and it worked fine.

          NSBundle *bundle = [NSBundle mainBundle];
          NSString *plistPath = [bundle pathForResource:@"Data" ofType:@"plist"];
          NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
          NSString *errorDesc = nil;
          NSPropertyListFormat format;
          NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
          NSString *lat = [temp objectForKey:@"Latitude"];
          NSString *lon = [temp objectForKey:@"Longitude"];

          It looks like your app might be trying to save information for a number of restaurants. Maybe that is why you have tried using an NSArray of the coordinates. I think you might be better off using Core Data for your app.

          If you had just one restaurant, a plist might be appropriate, but with multiple restaurants Core Data is probably the better way to go.

          http://www.theappcodeblog.com/?p=559

    • Kent says:

      Bal, that code was specific to the one users comment and retrieving coordinates from a plist. Go read the plist tutorial to see about doing that.

      • Bal says:

        ok that’s the function I also want to implement it to my structure.. I implemented this code to viewDidLoad NSBundle *bundle = [NSBundle mainBundle];
        NSString *plistPath = [bundle pathForResource:@"Coffeeshop" ofType:@"plist"];
        NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
        NSString *errorDesc = nil;
        NSPropertyListFormat format;
        NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
        NSString *lat = [temp objectForKey:@"Latitude"];
        NSString *lon = [temp objectForKey:@"Longitude"];

        but i keep this in line and that’s not right i think?
        location.latitude = 38.898748 ;
        location.longitude = -77.037684;

        It gives me also an unused variable “lat” and “lon”. Please can you help me with this, it will be very helpful.

        • Bal says:

          CLLocationCoordinate2D location = mapView.userLocation.coordinate;

          NSBundle *bundle = [NSBundle mainBundle];
          NSString *plistPath = [bundle pathForResource:@"Data" ofType:@"plist"];
          NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
          NSString *errorDesc = nil;
          NSPropertyListFormat format;
          NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];

          NSString *lat = [temp objectForKey:@"Latitude"];
          NSString *lon = [temp objectForKey:@"Longitude"];

          location.latitude = lat;
          location.longitude = lon;

          I’ve made it like this.. but I get errors on
          location.latitude = lat;
          location.longitude = lon;

          Can I sent you for example the code?

          • Kent says:

            Whoops replied to the other comment before I saw this one. You’ll need to convert lat and lon Strings into CLLocationDegrees I think.

        • Kent says:

          Without seeing the rest of your code or looking very closely I think you might want something like this;


          NSString *lat = [temp objectForKey:@"Latitude"];
          NSString *lon = [temp objectForKey:@"Longitude"];

          location.latitude = lat ;
          location.longitude = lon;

          But you’ll have to convert the lat and lon strings into CLLocationDegrees objects.

  4. Vall says:

    Hello,

    I follow your above code, and run it without problem, however when I changed the below two values:
    From:
    location.latitude = 38.898748 ;
    location.longitude = -77.037684;

    To:
    location.latitude = 121.7538921 ; //Taiwan
    location.longitude = 25.0999849; //Taiwan

    The program will crash, the console show:
    *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Invalid Region ‘

    What is the problem?

  5. Vall says:

    Hello,

    On this part:
    addAnnotation = [[AddressAnnotation alloc] initWithCoordinate:location];

    For IOS 5.0, the “initWithCoordinate” is deprecated and AddressAnnotation may not respond to “iniWithCoordinate”.

    How to use CLGeocoder class to implement for above project.

    Thanks!

    • Kent says:

      Hmmm, I’m afraid I don’t have the answer to that right off. I haven’t revisited it with iOS 5.0. I’ll see if I can revise it when I get a chance. Sorry I can’t be more help at the moment.

  6. vikram says:

    hello…can anybody tell me that how can i get Latitude and l
    ongitude of my Building in which i am sitting in my office????

  7. Dustin says:

    hey i this is a good map building guide and this is the first one that actually does what I’m looking for. but i have had a serious problem, iv fallowed your tutorial to the letter and iv had 15 problems in the very beginning when i would build it where as your tutorial says you had none. if you can would you help me out? thanks

    • Kent says:

      What were some of the errors you had? I might be able to help with a little more info.

      I also wonder if this could possibly be related to version differences. This tutorial was done a while back with Xcode 3.x and iOS 3.x I believe, don’t remember for sure. What is your environment?

  8. Roman says:

    Hi Kent,
    Thanks for this great tutorial ! The only one with really perfect explanations I have found. It helped me to get the really useful map in my app.
    Is there any possibility to set custom pin colours – red or blue ?
    Thanks !

  9. Osvaldo says:

    Hi Kent,

    I tried to add another subtitle but it doesn`t show. How do we add it so it shows in the map when we click the pin?

Add Comment Register



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>