Introduction to MapKit in iPhone OS 3.0

  • Twitter
  • Facebook
  • Digg
  • Reddit
  • StumbleUpon
  • del.icio.us
  • Google Bookmarks
December 21st, 2009 Posted by: (ELC) - posted under:Tutorials

Introduction

Hello everyone. Welcome to another screencast. Today we will be looking into the MapKit, a new API’s made available by Apple in the iPhone OS 3.0 release. The MapKit allows simple access to the map seen in the maps application. Using GoogleMaps as its engine the map kit allows for a developer to make their own custom map interface to fit their own application. Today we will be reviewing the MapView as well as the Map Annotations that can be used to highlight points of interest in a map. We will create our own custom map app, along with custom annotations. Let’s dive in.

Skill Level Intermediate

This tutorial is one for people familiar with general Objective C development and introductory experience to the iPhone SDK. Knowledge of general Interface Builder usage and DataSource and Delegate methods are required.

Screencast

I film myself coding out the entire sample project for each post. I personally think going through the Screencast is the best way to learn. But feel free to look through the slides and text if that suites you better.

Introduction to Map Kit on iPhone OS 3.0 from Collin Ruffenach on Vimeo.

Source

iCodeBlogMap Source

Tutorial

Introduction to MapKit on iPhone OS 3.001

Introduction to MapKit on iPhone OS 3.002

Introduction to MapKit on iPhone OS 3.003

Introduction to MapKit on iPhone OS 3.004

Introduction to MapKit on iPhone OS 3.005

Introduction to MapKit on iPhone OS 3.006

Introduction to MapKit on iPhone OS 3.007

Introduction to MapKit on iPhone OS 3.008

Introduction to MapKit on iPhone OS 3.009

Introduction to MapKit on iPhone OS 3.010

Introduction to MapKit on iPhone OS 3.011

Introduction to MapKit on iPhone OS 3.012

Introduction to MapKit on iPhone OS 3.013

Introduction to MapKit on iPhone OS 3.014

Introduction to MapKit on iPhone OS 3.015

Introduction to MapKit on iPhone OS 3.016

Introduction to MapKit on iPhone OS 3.017

Introduction to MapKit on iPhone OS 3.018

Introduction to MapKit on iPhone OS 3.019

Introduction to MapKit on iPhone OS 3.020

Introduction to MapKit on iPhone OS 3.021

Introduction to MapKit on iPhone OS 3.022

iCodeBlogMapViewController.h

#import "iCodeBlogAnnotation.h"
#import "iCodeBlogAnnotationView.h"
 
@interface iCodeMapViewController : UIViewController
{
	IBOutlet UITableView *tableview;
	IBOutlet MKMapView *mapView;
	IBOutlet UIImageView *shadowImage;
}
 
@property (nonatomic, retain) IBOutlet UITableView *tableview;
@property (nonatomic, retain) IBOutlet MKMapView *mapView;
@property (nonatomic, retain) IBOutlet UIImageView *shadowImage;
 
-(void)loadOurAnnotations;
 
@end

Introduction to MapKit on iPhone OS 3.023

iCodeBlogAnnoation.h

typedef enum {
	iCodeBlogAnnotationTypeApple = 0,
	iCodeBlogAnnotationTypeEDU = 1,
	iCodeBlogAnnotationTypeTaco = 2
} iCodeMapAnnotationType;
 
@interface iCodeBlogAnnotation : NSObject
{
	CLLocationCoordinate2D coordinate;
	NSString *title;
	NSString *subtitle;
	iCodeMapAnnotationType annotationType;
}
 
@property (nonatomic) CLLocationCoordinate2D coordinate;
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *subtitle;
@property (nonatomic) iCodeMapAnnotationType annotationType;
 
@end

Introduction to MapKit on iPhone OS 3.024

Introduction to MapKit on iPhone OS 3.025

Introduction to MapKit on iPhone OS 3.026

iCodeBlogAnnoation.m

@implementation iCodeBlogAnnotation
 
@synthesize coordinate;
@synthesize title;
@synthesize subtitle;
@synthesize annotationType;
 
-init
{
	return self;
}
 
-initWithCoordinate:(CLLocationCoordinate2D)inCoord
{
	coordinate = inCoord;
	return self;
}
 
@end

Introduction to MapKit on iPhone OS 3.027

iCodeBlogAnnoationView.h

@interface iCodeBlogAnnotationView : MKAnnotationView
{
	UIImageView *imageView;
}
 
@property (nonatomic, retain) UIImageView *imageView;
 
@end

Introduction to MapKit on iPhone OS 3.028

Introduction to MapKit on iPhone OS 3.029

Introduction to MapKit on iPhone OS 3.030

Images to Use

AppleMarker

SchoolMarker

TacosMarker



iCodeBlogAnnoationView.m

#import "iCodeBlogAnnotationView.h"
 
@implementation iCodeBlogAnnotationView
 
@synthesize imageView;
 
#define kHeight 40
#define kWidth  37
#define kBorder 2
 
- (id)initWithAnnotation:(id )annotation reuseIdentifier:(NSString *)reuseIdentifier
{
	iCodeBlogAnnotation* myAnnotation = (iCodeBlogAnnotation*)annotation;
 
	if([myAnnotation annotationType] == iCodeBlogAnnotationTypeApple)
	{
		self = [super initWithAnnotation:myAnnotation reuseIdentifier:reuseIdentifier];
		self.frame = CGRectMake(0, 0, kWidth, kHeight);
		self.backgroundColor = [UIColor clearColor];
 
		imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"AppleMarker.png"]];
		imageView.frame = CGRectMake(kBorder, kBorder, kWidth - 2 * kBorder, kWidth - 2 * kBorder);
		[self addSubview:imageView];
	}
 
	else if([myAnnotation annotationType] == iCodeBlogAnnotationTypeEDU)
	{
		self = [super initWithAnnotation:myAnnotation reuseIdentifier:reuseIdentifier];
		self.frame = CGRectMake(0, 0, kWidth, kHeight);
		self.backgroundColor = [UIColor clearColor];
 
		imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SchoolMarker.png"]];
		imageView.frame = CGRectMake(kBorder, kBorder, kWidth - 2 * kBorder, kWidth - 2 * kBorder);
		[self addSubview:imageView];
	}
 
	else if([myAnnotation annotationType] == iCodeBlogAnnotationTypeTaco)
	{
		self = [super initWithAnnotation:myAnnotation reuseIdentifier:reuseIdentifier];
		self.frame = CGRectMake(0, 0, kWidth, kHeight);
		self.backgroundColor = [UIColor clearColor];
 
		imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TacosMarker.png"]];
		imageView.frame = CGRectMake(kBorder, kBorder, kWidth - 2 * kBorder, kWidth - 2 * kBorder);
		[self addSubview:imageView];
	}
 
	[imageView setContentMode:UIViewContentModeScaleAspectFill];
 
	return self;
}
 
@end

Introduction to MapKit on iPhone OS 3.031

Introduction to MapKit on iPhone OS 3.032

iCodeBlogMapViewController.m

-(void)loadOurAnnotations
{
	CLLocationCoordinate2D workingCoordinate;
 
	workingCoordinate.latitude = 40.763856;
	workingCoordinate.longitude = -73.973034;
	iCodeBlogAnnotation *appleStore1 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[appleStore1 setTitle:@"Apple Store 5th Ave."];
	[appleStore1 setSubtitle:@"Apple's Flagship Store"];
	[appleStore1 setAnnotationType:iCodeBlogAnnotationTypeApple];
 
	[mapView addAnnotation:appleStore1];
 
	workingCoordinate.latitude = 51.514298;
	workingCoordinate.longitude = -0.141949;
	iCodeBlogAnnotation *appleStore2 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[appleStore2 setTitle:@"Apple Store St. Regent"];
	[appleStore2 setSubtitle:@"London England"];
	[appleStore2 setAnnotationType:iCodeBlogAnnotationTypeApple];
 
	[mapView addAnnotation:appleStore2];
 
	workingCoordinate.latitude = 35.672284;
	workingCoordinate.longitude = 139.765702;
	iCodeBlogAnnotation *appleStore3 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[appleStore3 setTitle:@"Apple Store Giza"];
	[appleStore3 setSubtitle:@"Tokyo, Japan"];
	[appleStore3 setAnnotationType:iCodeBlogAnnotationTypeApple];
 
	[mapView addAnnotation:appleStore3];
 
	workingCoordinate.latitude = 37.331741;
	workingCoordinate.longitude = -122.030564;
	iCodeBlogAnnotation *appleStore4 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[appleStore4 setTitle:@"Apple Headquarters"];
	[appleStore4 setSubtitle:@"The Mothership"];
	[appleStore4 setAnnotationType:iCodeBlogAnnotationTypeApple];
 
	[mapView addAnnotation:appleStore4];
 
	workingCoordinate.latitude = 41.894518;
	workingCoordinate.longitude = -87.624005;
	iCodeBlogAnnotation *appleStore5 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[appleStore5 setTitle:@"Apple Store Michigan Ave."];
	[appleStore5 setSubtitle:@"Chicago, IL"];
	[appleStore5 setAnnotationType:iCodeBlogAnnotationTypeApple];
 
	[mapView addAnnotation:appleStore5];
 
	workingCoordinate.latitude = 32.264977;
	workingCoordinate.longitude = -110.944011;
	iCodeBlogAnnotation *tacoShop1 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[tacoShop1 setTitle:@"Nico's Taco Shop"];
	[tacoShop1 setSubtitle:@"Tucson, AZ"];
	[tacoShop1 setAnnotationType:iCodeBlogAnnotationTypeTaco];
 
	[mapView addAnnotation:tacoShop1];
 
	workingCoordinate.latitude = 32.743242;
	workingCoordinate.longitude = -117.181451;
	iCodeBlogAnnotation *tacoShop2 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[tacoShop2 setTitle:@"Lucha Libre Gourmet"];
	[tacoShop2 setSubtitle:@"San Diego, CA"];
	[tacoShop2 setAnnotationType:iCodeBlogAnnotationTypeTaco];
 
	[mapView addAnnotation:tacoShop2];
 
	workingCoordinate.latitude = 32.594987;
	workingCoordinate.longitude = -117.060936;
	iCodeBlogAnnotation *tacoShop3 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[tacoShop3 setTitle:@"El Ranchero Taco Shop"];
	[tacoShop3 setSubtitle:@"Rocky Pointe, Mexico"];
	[tacoShop3 setAnnotationType:iCodeBlogAnnotationTypeTaco];
 
	[mapView addAnnotation:tacoShop3];
 
	workingCoordinate.latitude = -34.594859;
	workingCoordinate.longitude = -58.384336;
	iCodeBlogAnnotation *tacoShop4 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[tacoShop4 setTitle:@"Taco Tequila Sangria S.A."];
	[tacoShop4 setSubtitle:@"Buneos Aires, Argentina"];
	[tacoShop4 setAnnotationType:iCodeBlogAnnotationTypeTaco];
 
	[mapView addAnnotation:tacoShop4];
 
	workingCoordinate.latitude = 38.240550;
	workingCoordinate.longitude = -0.526509;
	iCodeBlogAnnotation *tacoShop5 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[tacoShop5 setTitle:@"Albertsma Taco"];
	[tacoShop5 setSubtitle:@"Gran Alacant, Spain"];
	[tacoShop5 setAnnotationType:iCodeBlogAnnotationTypeTaco];
 
	[mapView addAnnotation:tacoShop5];
 
	workingCoordinate.latitude = 33.419490;
	workingCoordinate.longitude = -111.930563;
	iCodeBlogAnnotation *school1 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[school1 setTitle:@"Arizona State University"];
	[school1 setSubtitle:@"Go Sun Devils"];
	[school1 setAnnotationType:iCodeBlogAnnotationTypeEDU];
 
	[mapView addAnnotation:school1];
 
	workingCoordinate.latitude = 35.087537;
	workingCoordinate.longitude = -106.618184;
	iCodeBlogAnnotation *school2 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[school2 setTitle:@"University of New Mexico"];
	[school2 setSubtitle:@"Go Lobos"];
	[school2 setAnnotationType:iCodeBlogAnnotationTypeEDU];
 
	[mapView addAnnotation:school2];
 
	workingCoordinate.latitude = 40.730838;
	workingCoordinate.longitude = -73.997498;
	iCodeBlogAnnotation *school3 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[school3 setTitle:@"New York University"];
	[school3 setSubtitle:@"New York, NY"];
	[school3 setAnnotationType:iCodeBlogAnnotationTypeEDU];
 
	[mapView addAnnotation:school3];
 
	workingCoordinate.latitude = 51.753523;
	workingCoordinate.longitude = -1.253171;
	iCodeBlogAnnotation *school4 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[school4 setTitle:@"Oxford University"];
	[school4 setSubtitle:@"Oxford, England"];
	[school4 setAnnotationType:iCodeBlogAnnotationTypeEDU];
 
	[mapView addAnnotation:school4];
 
	workingCoordinate.latitude = 22.131982;
	workingCoordinate.longitude = 82.142302;
	iCodeBlogAnnotation *school5 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
	[school5 setTitle:@"India Institute of Technology"];
	[school5 setSubtitle:@"Delhi, India"];
	[school5 setAnnotationType:iCodeBlogAnnotationTypeEDU];
 
	[mapView addAnnotation:school5];
}

Introduction to MapKit on iPhone OS 3.033

iCodeblogMapViewController.m

- (iCodeBlogAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation
{
	iCodeBlogAnnotationView *annotationView = nil;
 
	// determine the type of annotation, and produce the correct type of annotation view for it.
	iCodeBlogAnnotation* myAnnotation = (iCodeBlogAnnotation *)annotation;
 
	if(myAnnotation.annotationType == iCodeBlogAnnotationTypeApple)
	{
		NSString* identifier = @"Apple";
		iCodeBlogAnnotationView *newAnnotationView = (iCodeBlogAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
 
		if(nil == newAnnotationView)
		{
			newAnnotationView = [[[iCodeBlogAnnotationView alloc] initWithAnnotation:myAnnotation reuseIdentifier:identifier] autorelease];
		}
 
		annotationView = newAnnotationView;
	}
	else if(myAnnotation.annotationType == iCodeBlogAnnotationTypeEDU)
	{
		NSString* identifier = @"School";
 
		iCodeBlogAnnotationView *newAnnotationView = (iCodeBlogAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
 
		if(nil == newAnnotationView)
		{
			newAnnotationView = [[[iCodeBlogAnnotationView alloc] initWithAnnotation:myAnnotation reuseIdentifier:identifier] autorelease];
		}
 
		annotationView = newAnnotationView;
	}
	else if(myAnnotation.annotationType == iCodeBlogAnnotationTypeTaco)
	{
		NSString* identifier = @"Taco";
 
		iCodeBlogAnnotationView *newAnnotationView = (iCodeBlogAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
 
		if(nil == newAnnotationView)
		{
			newAnnotationView = [[[iCodeBlogAnnotationView alloc] initWithAnnotation:myAnnotation reuseIdentifier:identifier] autorelease];
		}
 
		annotationView = newAnnotationView;
	}
 
	[annotationView setEnabled:YES];
	[annotationView setCanShowCallout:YES];
 
	return annotationView;
}

Introduction to MapKit on iPhone OS 3.034

Introduction to MapKit on iPhone OS 3.035

iCodeBlogMapViewController.m

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 3;
}

Introduction to MapKit on iPhone OS 3.036

iCodeBlogMapViewController.m

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
	if(section == iCodeBlogAnnotationTypeApple)
	{
		return @"Apple Markers";
	}
 
	else if(section == iCodeBlogAnnotationTypeEDU)
	{
		return @"Schools";
	}
 
	else if(section == iCodeBlogAnnotationTypeTaco)
	{
		return @"Taco Shops";
	}
 
	return nil;
}

Introduction to MapKit on iPhone OS 3.037

iCodeBlogMapViewController.m

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	return 5;
}

Introduction to MapKit on iPhone OS 3.038

Introduction to MapKit on iPhone OS 3.039

iCodeBlogMapViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 
	if (cell == nil)
	{
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
 
	NSMutableArray *annotations = [[NSMutableArray alloc] init];
 
	if(indexPath.section == 0)
	{
		for(iCodeBlogAnnotation *annotation in [mapView annotations])
		{
			if([annotation annotationType] == iCodeBlogAnnotationTypeApple)
			{
				[annotations addObject:annotation];
			}
		}
 
		cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
	}
 
	else if(indexPath.section == 1)
	{
		for(iCodeBlogAnnotation *annotation in [mapView annotations])
		{
			if([annotation annotationType] == iCodeBlogAnnotationTypeEDU)
			{
				[annotations addObject:annotation];
			}
		}
 
		cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
	}
 
	else if(indexPath.section == 2)
	{
		for(iCodeBlogAnnotation *annotation in [mapView annotations])
		{
			if([annotation annotationType] == iCodeBlogAnnotationTypeTaco)
			{
				[annotations addObject:annotation];
			}
		}
 
		cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
	}
 
    return cell;
}

Introduction to MapKit on iPhone OS 3.040

Introduction to MapKit on iPhone OS 3.041

iCodeBlogMapViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
	for(iCodeBlogAnnotation *annotation in [mapView annotations])
	{
		if([[[[tableView cellForRowAtIndexPath:indexPath] textLabel] text] isEqualToString:[annotation title]])
		{
			[mapView setRegion:MKCoordinateRegionMake([annotation coordinate], MKCoordinateSpanMake(.01, .01)) animated:YES];
		}
	}
}
  • http://www.grumpydev.com Steve Robbins

    Nice post and good timing for me, thanks :-) Do you know if it’s currently possible to use your own map graphic, rather than use the standard satellite, hybrid, road graphics? I have a sneaking suspicion I’m going to have to “roll my own” map to support that, but if you know of a way to do it with the standard MapKit that would be great :-)

    Cheers!

  • Andre

    I too am wondering the same thing. Is there any support for custom tiles and custom pin icons?

    How would one go about making their own map interface for small-sized maps?

  • purplehairymonster

    Thanks so much for this tutorial! It has been very useful and informative. Just wondering how would you go about showing only one country eg. France when the application loads? Thanks again :)

  • http://leemills.tumblr.com Lee

    Excellent tutorial there, been playing around with my own custom annotations based upon this but I have been unable to implement the showUserLocation property since using this, any ideas as to why it would crash the application?

  • Rich

    Great tutorial!! Thanks!!

    I am wondering how a user and enter an actual address and have it translated into lay/long? If there is a MKReverseGeocoder, how come Apple did make a MKGoecoder class?

  • Tom Biagioni

    Exactly what I needed to move forward.

    I am having one problem though, i’m trying to modify the source to allow for user location, but I get this error:

    2009-09-30 09:54:10.374 iCodeMap[788:207] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[MKUserLocation annotationType]: unrecognized selector sent to instance 0x4504b80′

    I’m thinking i need to allow for enter in a nil clause that allows for basic annotations to be displayed– or maybe just expand the enum– but i’m not sure how to do it.

    how can i change the MKUserLocation annotation?

  • FF

    Really wondering how the hell could i use “showUserLocation” without crashing…

  • Mustafa

    Can you please make the screencast video available for download. Thanks.

  • http://www.allinghana.com Rinkart

    Hello, thanks a lot for the tutorial. I am in a student in Ghana, I want to get the nearest distance to a marked annotation. Can anyone help me out?

  • Carl Grainger

    Another great screencast, making it all so easy. Definitely One to Watch. Big thanks for sharing your work.

  • http://www.maluspumila.net Justin

    I’m getting an error when I compile the delegate method for the mapView.

    - (iCodeBlogAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation {

    ///rest of code here…..
    }

    The error says: “Incompatible Objective-C types initializing ‘struct MKAnnotationView *’, expected ‘struct iCodeBlogAnnotationView *’

    The delegate method is called properly when the mapView is displayed, but because of this error crashes….

    any ideas from anyone??

  • http://www.maluspumila.net Justin

    Alright, I got past my last issue. Not entirely sure at this point, what I did….???? Oh well.

    Now the problem of the day, and it’s the same problem others have posted about.

    How to show the user location now, when you have that map delegate. When you apply the mapView.showUserLocation = YES; It goes into the mapView delegate you have us using, to use custom annotations, but it crashes when showing user location annotation. The error is what is reported by: Tom Biagioni & FF – above.

    Any help from anyone. When you have that delegate defined, it’s expecting you to pass in an annotation. When it’s called because you’ve got mapView.showUserLocation = YES; it is passing the wrong type of information…

    uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[MKUserLocation annotationType]: unrecognized selector sent to instance

  • http://www.maluspumila.net Justin

    If you set the mapView.showUserLocation = YES; and you do not have the delegate method: – (iCodeBlogAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation

    everything works ok, except now we don’t get the custom annotation feature. How can we have our cake & eat it too?

  • Tom Biagioni

    OK guys, I figured this out a while ago but totally forgot to post it, so here is the solution:

    step one: add the CoreLocation framework to the project.

    Step two: add this function to the iCodeMapViewController.m:


    - (void)setCurrentLocation:(CLLocation *)location {
    MKCoordinateRegion region = {{0.0f, 0.0f}, {0.0f, 0.0f}};
    region.center = location.coordinate;
    region.span.longitudeDelta = 0.15f;
    region.span.latitudeDelta = 0.15f;
    [self.mapView setRegion:region animated:YES];
    }

    step three: add this code to the ViewForAnnotation Method:


    if (annotation != mapView.userLocation) {
    //the rest of the ViewForAnnotation code goes here
    }else{
    CLLocation *location = [[CLLocation alloc]
    initWithLatitude:annotation.coordinate.latitude
    longitude:annotation.coordinate.longitude];
    [self setCurrentLocation:location];
    }

    you can change the setCurrentLocation method however you want, right now it is set to zoom in on the current location, which doesn’t seem all that helpful for this particular tutorial… but that should do it! hope it works for you!

  • http://www.allinghana.com Rinkart

    hello Toni Biagioni, I have implemented your method for showing the current loaction of the user, but it gives me this error-”.objc_class_CCLocation”, referenced from:
    literal-pointer@__OBJC@__cls_refs@CLLocation in iCodeMapViewController.o

    please help

  • Tom Biagioni

    @rinkart: you need to add the core location framework to your project

  • http://www.allinghana.com Rinkart

    @Tom: I have tom, but have the same error.

  • http://www.allinghana.com Rinkart

    @Tom: I did a clean, and IT WORKED, thanks. where is the current location set? I cant find it.

  • http://www.maluspumila.net Justin

    Nice Work! That did the trick. I guess the key was creating a condition where you wouldn’t be attempting to pass annotationType to the userLocation annotation.

    Thanks again! Watch out for the app – “Access My Library” coming soon! Allows you the ability to access all kinds of free material from your local library via your iphone/ipod touch.

  • http://www.allinghana.com Rinkart

    @Tom: I have implemented the steps, i have no errors but still cannot see the user location.

  • Tom Biagioni

    @rinkart: it’s there, just hidden behind one of the annotations Collin added to the apple annotation type. comment out the following code and youll see it


    /*
    workingCoordinate.latitude = 37.331741;
    workingCoordinate.longitude = -122.030564;
    iCodeBlogAnnotation *appleStore4 = [[iCodeBlogAnnotation alloc] initWithCoordinate:workingCoordinate];
    [appleStore4 setTitle:@"Apple Headquarters"];
    [appleStore4 setSubtitle:@"The Mothership"];
    [appleStore4 setAnnotationType:iCodeBlogAnnotationTypeApple];

    [mapView addAnnotation:appleStore4];
    */

  • Vishnu

    Hi,

    Thanks for sharing your work. Great tutorial!!

    When I build the source code, the app opened as shown below. At the background I could see only a graph kind of pattern with pins(figures) and no map.

    /Users/308329/Desktop/Picture 2.png

    How do I get it right?

    Any help on this would be highly appreciated.

    Thanks in advance.

  • http://www.allinghana.com Rinkart

    @Tom: thanks a lot for the help. i’ve seen the current location. I’ve implemented a parking space finder application with this. I have added options to change preferences of the mapview based on some selection criteria and i want to reload the map anytime a user selects any of these critiria. Can you pls offer help?

  • Justin

    Thanks for the video!

  • Anonymous

    To get the built in user location to work simply do this:

    -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation
    {
    	if ([annotation isKindOfClass:MKUserLocation.class]) return nil;
            //rest of code
    }
    
  • ejpusa

    On adding the framework, you reference vs copy over. Is there a problem if you do click the check box and copy the framework?

    I always default to copy, so far no problems, just wondering what the rule of thumb is.

    thanks

  • Danny

    Very awesome. Do you know if you can draw on a map? ie. mark a green line along a block for places you can park or something. Would I have to resort to using Quartz or something?

  • Iphone Dev

    Hi,

    This tutorial is very nice and saved my a lot.

    i need to do like when i press on AnnotationView and it should goes to detailed view of that result.

    I got method – (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control.

    but i dont know that what to do in that method. If anyone has done this then pls drop some code here.

    Thanks so much.

  • Matteo

    @Iphone Dev

    I think you need to set your annotation in this delegate’s function, like:

    - (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id ) annotation{

    MKAnnotationView *annView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"current loc"];
    annView=[[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@”current loc”]autorelease];

    //this set your annotation to be tappable
    annView.canShowCallout = YES;

    //set the blue button on the right of the annotation
    annView.rightCalloutAccessoryView=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];

    }
    //sorry for my bad english!!
    Bye!

  • Harpreet

    Very informative tutorial.

    I want to make a small random number generator app and wanted to know if there is a way to initiate an IBAction implicitly during the launch of the application.

    Thanks,
    Harpreet

  • Digiguy

    Hi all,
    Great work on this.. .but I too am having some warning on build.
    - (iCodeBlogAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation
    {
    WARNING: INITIALIZATION FROM A DISTINCT OBJECTIVE C TYPE
    iCodeBlogAnnotationView *annotationView = nil;

    if (annotation != mapView.userLocation)
    WARNING: LOCAL DELARATION OF ‘MAPVIEW’ HIDES INSTANCE VARIABLE
    {
    //the rest of the ViewForAnnotation code goes here
    iCodeBlogAnnotation* myAnnotation = (iCodeBlogAnnotation *)annotation;
    if(myAnnotation.annotationType == iCodeBlogAnnotationTypeApple)
    {
    NSString* identifier = @”Apple”;
    iCodeBlogAnnotationView *newAnnotationView = (iCodeBlogAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    ………… rest of old code………
    }

    [annotationView setEnabled:YES];
    [annotationView setCanShowCallout:YES];
    }else{
    CLLocation *location = [[CLLocation alloc]
    initWithLatitude:annotation.coordinate.latitude
    longitude:annotation.coordinate.longitude];
    [self setCurrentLocation:location];
    }

    return annotationView;
    }
    It would be great if you could put all the mods here mentioned back into the source code. We would really appreciate it, and make a more complete tutorial, as the code isn’t working right, and hard to learn when it isn’t quite all there. Thanks guys… love the site!

    Sincerely,
    Kirk

  • Digiguy

    … I have of course added the CoreLocation.Fraameworh Resources, cleaned run… still the errors.

    Sincerely,
    Kirk

  • Rachel

    @Tom Biagioni

    I’m getting the same “Terminating app due to uncaught exception ‘NSInvalidArgumentException’…” error. I’m wondering if you ever managed to figure out the problem?

    Cheers,
    Rachel

  • Abhishek

    hello very nice tutorial………,
    WhileYou being an iphone guru, i wanted ask you something.Do you know a GPS device that actually sends outs signals that the iphone can capture and convert it into latitudes and longitudes which u can use to track that device(using the Mapkit framework)?

  • Yoot

    Hi,

    thanks a lot for this tutorial, I’ve one problem though, in the MKMapView I can only see an empty grid, without any map displayed on it…

    Any idea of what’s going on ?

  • Sam

    Hi there, Outstanding tutorial, totally helped to understand the mapkit, I got one problem, am trying to push to a view controller for each pin ?I already have abutton in each annotation with the title there,but it just cant go through! I will be so thankful if anyone helped me on this please.

  • Sijo

    Can u help me in my problem.. I have to show 4 lines of data in that bubble..Like One title..then description, date, location name.. All the example showing only 2 lines of details. i tried like appending wanted data in subtitle and seperated by a \n character.. But it didnt worked.. Plz help me

  • Wierboy

    I would also like to thank you for the very helpful tutorial!

    I am having a problem, however, in that everything seems to be working properly with the exception that I am still seeing red pins instead of my custom annotation view. No errors, compiles and runs perfectly.

    In the code snippet below, “It’s a bank” is being written to the log so this code is being called and the conditional is correctly identifying the fact that the annotation being added is of type MyAppAnnotationTypeBank. I also changed the tutorial’s clearColor to redColor in case the problem was with the image but I see no red background color.

    Any suggestions would be greatly appreciated!!

    Thanks!

    ——————————-

    - (id)initWithAnnotation:(id )annotation reuseIdentifier:(NSString *)reuseIdentifier {

    MyAppAnnotation *myAnnotation = (MyAppAnnotation*)annotation;

    if([myAnnotation annotationType] == MyAppAnnotationTypeBank) {
    NSLog(@”It’s a bank”);
    self = [super initWithAnnotation:myAnnotation reuseIdentifier:reuseIdentifier];
    self.frame = CGRectMake(0, 0, kHeight, kWidth);
    self.backgroundColor = [UIColor redColor];

    imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bank.png"]];
    imageView.frame = CGRectMake(kBorder, kBorder, kWidth – 2 * kBorder, kHeight – 2 * kBorder);
    [self addSubview:imageView];
    } …

  • http://www.markasherswanson.com/post/SQUIRREL.aspx Lee Mcpeck

    Very good piece of content, this is very similar to a site that I have. Please check it out sometime and feel free to leave me a comenet on it and tell me what you think. Im always looking for feedback.

  • teddafan

    Hi,

    First, thank you very much for your very complete tutorial! I truly think it is the best around with the widest use of Mapkit.

    Could someone tell me how it would possible to list in the tableView the annotations in order of distance to the distance location?

    I thank you in advance for your help,

    Cheers

    teddafan

  • eduardo

    Thanks GREAT TUTORIAL!!! The best!!!!

  • lib

    Hi!! great tutorial but i was wondering i want the tableview be the full size of the window and also the map, do i need to create and extra xib for the tableview? or is other simple way posible? hope u can help me

    thanks

  • vinay

    I have tried this example ..But i had some errors while scroll down the rows in table..
    I have set the showUserLocation=YES;
    and in viewForAnnotaion method i have added this line
    if ([annotation isKindOfClass:MKUserLocation.class]) return nil;
    Also i added the coreLocation framework as well.But i am getting the following error when i scroll down the contents in the table..
    [MKUserLocation annotationType]: unrecognized selector sent to instance 0x6b63250′

    Help me..

  • vinay_iphone

    I have used this sample..I am getting the following error when scrolling down the rows in table..

    [MKUserLocation annotationType]: unrecognized selector sent to instance 0x6b63250′

    i have set the showUserloaction:YES and
    if ([annotation isKindOfClass:MKUserLocation.class]) return nil; in the annotationViewmethod.
    Also i added the coreLocationFramework as well..

  • Milena

    Does anyone here knows how to reference to a kml file instead of the hardcoded data used in this tutorial? Thanks!

  • favormm

    hi,
    When showUserLocation = YES, will show a blue dot and a circle on the map. can we change the circle color and change the blue dot to a image?

    Thanks very much.

  • Shiim

    I’ve got the same problem as vinay has – the app crashes when trying to roll the table after tapping the button which calls IBAction to show user location.
    Probably the table tries to set the location annotation as a cell or smth.

  • Shiim

    Problem solved.
    In cellForRowatIndexPath I did this:


    NSMutableArray *annotations = [[NSMutableArray alloc] init];
    if(indexPath.section == 0)
    {
    for(MinuAsukohad *annotation in [mapView annotations])
    {
    if(![annotation isKindOfClass:[MKUserLocation class]])
    {
    if([annotation annotationType] == MinuAsukohadTypeInterest)
    {
    [annotations addObject:annotation];
    }
    }
    }
    cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
    }

    You just have to repeat it for all the sections.

  • Shiim

    Why does the Instruments tool show a leak on
    NSMutableArray *annotations = [[NSMutableArray alloc] init]; ?

  • James

    hi I was wounding how you could add buttons instead of the title and subtitle and if you can’t can you tell me how to add a detail diclosed button.
    Thanks

  • Eden

    Hi Colin,

    This is a very great tutorial.

    I have a question to add more cell in each section, bcos in my project, i have only 2 section, 1st section have 65 cells and 2nd section have 60 cells, i try to change the section from “return 3″ to “return 2″ it works.

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
    return 2;
    }

    But when i change the cell from “return 5″ to “return 65″, it doesn’t work.

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
    return 65;
    }

    Can you pls teach me how to change this code are able to fulfill my requirement ?

    Thank you very much !

    Regards,
    eden
    eden_yap@live.com/

  • Stinkyh

    Great post, thanks. Just one thing… it’s not Saint Regent lol (as you said in your video) it’s Regent Street (the St. stand for street). Not particularly relevant but hey.

  • harry

    Even I am trying to do this .If you completed with this then help me out from this condition .

  • raja

    Hi,
    I am also want this this in my app can you.If completed with so can help me out

  • Gina

    Great tutorial. I’m really trying to get my head around MapKit and this was amazing. It’s a huge difference to listen to your screencast as opposed to just reading. I know it’s a lot of work but I loved it.

    I’m getting a run-time error, tho. The app crashes immediately with the following message. Please help :)

    2011-04-28 14:00:42.849 IcodeBlogMap[1837:207] *** Terminating app due to uncaught exception ‘NSUnknownKeyException’, reason: ‘[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key tableView.’

  • MapView

    Please share the code/concept of how you solved this. (if you have)

blog comments powered by Disqus