Setting region in MKMapView - iphone

I have 10 - 15 lat long to show in map at a time. How should I set region so that I can see all the annotations on the map.

create class as below. create two class: ViewController is class of UIViewController and MapViewAnnotation is class of NSObject. I have created that two class as below. bind mapview in XIB of ViewController and set delegate.
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "MapViewAnnotation.h"
#interface ViewController : UIViewController<MKMapViewDelegate>{
IBOutlet MKMapView* mapView;
NSMutableArray *arrayLocation;
}
#end
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
arrayLocation = [[NSMutableArray alloc]init];
NSMutableArray *arrAnnotations = [[NSMutableArray alloc]init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.774125" forKey:#"latitude"];
[dict setValue:#"-117.240658" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 1" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.784526" forKey:#"latitude"];
[dict setValue:#"-117.240985" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 2" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.773477" forKey:#"latitude"];
[dict setValue:#"-117.241144" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 3" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.775301" forKey:#"latitude"];
[dict setValue:#"-117.238893" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 4" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
for(int i=0;i<[arrayLocation count];i++)
{
CLLocationCoordinate2D location;
location.latitude = [[[arrayLocation objectAtIndex:i] objectForKey:#"latitude"] doubleValue];
location.longitude = [[[arrayLocation objectAtIndex:i] objectForKey:#"longitude"] doubleValue];
MapViewAnnotation *newAnnotation = [[MapViewAnnotation alloc] initWithTitle:[[arrayLocation objectAtIndex:i] objectForKey:#"title"] Coordinate:location andIndex:i];
[arrAnnotations addObject:newAnnotation];
}
[mapView addAnnotations:arrAnnotations];
mapView.region = [MapViewAnnotation regionForAnnotations:arrAnnotations];
}
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
if (annotation == mapView.userLocation)
{
return nil;
}
MKPinAnnotationView *pin = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier: #"restMap"];
if (pin == nil)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"restMap"];
}
else
{
pin.annotation = annotation;
}
pin.pinColor = MKPinAnnotationColorRed;
pin.animatesDrop = NO;
pin.canShowCallout=TRUE;
UIButton *btn=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
MapViewAnnotation *temp = (MapViewAnnotation *)pin.annotation;
btn.tag=temp.index;
pin.rightCalloutAccessoryView=btn;
[btn addTarget:self action:#selector(openDetail:) forControlEvents:UIControlEventTouchUpInside];
return pin;
}
#end
Implementation of MapViewAnnotation class
#import <MapKit/MapKit.h>
#interface MapViewAnnotation : NSObject <MKAnnotation , MKMapViewDelegate>{
NSString *title;
int index;
CLLocationCoordinate2D coordinate;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readwrite) int index;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d;
- (id)initWithTitle:(NSString *)ttl Coordinate:(CLLocationCoordinate2D)c2d andIndex:(int)intIndex;
+(MKCoordinateRegion) regionForAnnotations:(NSArray*) annotations ;
#end
#import "MapViewAnnotation.h"
#implementation MapViewAnnotation
#synthesize title, coordinate,index;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d {
self = [super init];
title = ttl;
coordinate = c2d;
return self;
}
- (id)initWithTitle:(NSString *)ttl Coordinate:(CLLocationCoordinate2D)c2d andIndex:(int)intIndex
{
self = [super init];
title = ttl;
coordinate = c2d;
index = intIndex;
return self;
}
+(MKCoordinateRegion) regionForAnnotations:(NSArray*) annotations
{
NSAssert(annotations!=nil, #"annotations was nil");
NSAssert([annotations count]!=0, #"annotations was empty");
double minLat=360.0f, maxLat=-360.0f;
double minLon=360.0f, maxLon=-360.0f;
for (id<MKAnnotation> vu in annotations) {
if ( vu.coordinate.latitude < minLat ) minLat = vu.coordinate.latitude;
if ( vu.coordinate.latitude > maxLat ) maxLat = vu.coordinate.latitude;
if ( vu.coordinate.longitude < minLon ) minLon = vu.coordinate.longitude;
if ( vu.coordinate.longitude > maxLon ) maxLon = vu.coordinate.longitude;
}
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((minLat+maxLat)/2.0, (minLon+maxLon)/2.0);
MKCoordinateSpan span = MKCoordinateSpanMake(maxLat-minLat, maxLon-minLon);
MKCoordinateRegion region = MKCoordinateRegionMake (center, span);
return region;
}
#end

If anyone is looking for a Swift 3 solution, I've written this quick extension that works very well for me :)
public extension MKMapView {
public static func visibleRect(for coords: [CLLocationCoordinate2D]) -> MKMapRect {
return coords.reduce(MKMapRectNull) { outRect, coord in
let point = MKMapPointForCoordinate(coord)
let rect = MKMapRectMake(point.x, point.y, 0.1, 0.1)
let union = MKMapRectUnion(rect, outRect)
return union
}
}
public func fitCoordinates(_ coords: [CLLocationCoordinate2D],
animated: Bool = true,
insets: UIEdgeInsets = UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25)) {
let rect = MKMapView.visibleRect(for: coords)
self.setVisibleMapRect(rect, edgePadding: insets, animated: animated)
}
}
Which allows to quickly do:
map.fitCoordinates([userLocation, location1, location2])
Hope this helps anyone!
Gist here: https://gist.github.com/freak4pc/1748322a1b8bba23b6de3f47cb00c3ea

try like this may be it helps you,
MKCoordinateSpan span = MKCoordinateSpanMake(52.0f,80.0001f);
CLLocationCoordinate2D coordinate = {8.9999, 18.2812};
MKCoordinateRegion region = {coordinate, span};
MKCoordinateRegion regionThatFits = [self.mapView regionThatFits:region];
NSLog(#"Fit Region %f %f", regionThatFits.center.latitude, regionThatFits.center.longitude);
[self.mapView setRegion:regionThatFits animated:YES];
replace your coordinates and all the values respectively.

For Show All Annotation use this method, i Used this Method in same issue as your. it worked for me.
-(void)zoomToFitMapAnnotations:(MKMapView*)mapView
{
if([mapView.annotations count] == 0)
return;
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(MYAnnotation* annotation in mapView.annotations)// here MYAnnotation is custom annotation call.
{
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
NSLog(#"A%f, B%f, C%f, D%f,", topLeftCoord.latitude, topLeftCoord.longitude, bottomRightCoord.latitude, bottomRightCoord.longitude);
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1;
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1;
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:YES];
}
call this method after set all Place(Annotation) on Map View, such like..
[self zoomToFitMapAnnotations:self.mapView];

Related

Add image to the left of my annotations

I have created annotations that show up perfectly on my map but I am not sure how to implement the leftCalloutAccessoryView to show images.
MapViewAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MapViewAnnotation : NSObject <MKAnnotation>
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
MapViewAnnotation.m
#import "MapViewAnnotation.h"
#implementation MapViewAnnotation
#synthesize coordinate, title, subtitle;
#end
GroundsViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface GroundsViewController : UIViewController <MKMapViewDelegate>
{
MKMapView *mapView;
}
#property (strong, nonatomic) IBOutlet UISegmentedControl *segment;
- (IBAction)changeSeg:(id)sender;
#end
GroundsViewController.m
#import "GroundsViewController.h"
#import "MapViewAnnotation.h"
#interface GroundsViewController ()
#end
// Centre in on Northern Ireland
#define Northern_Ireland_Latitude 54.629338;
#define Northern_Ireland_Longitude -6.668701;
//Span
#define The_Span 2.00f;
// Premiership
#define Ballymena_Latitude 54.870105;
#define Ballymena_Longitude -6.265076;
// Championship 1
#define Ards_Latitude 54.651629;
#define Ards_Longitude -5.684478;
// Championship 2
#define Annagh_Latitude 54.411372;
#define Annagh_Longitude -6.440355;
#implementation GroundsViewController
#synthesize segment;
- (IBAction)changeSeg:(id)sender {
if (segment.selectedSegmentIndex == 0) {
mapView.mapType = MKMapTypeStandard;
}
if (segment.selectedSegmentIndex == 1) {
mapView.mapType = MKMapTypeSatellite;
}
if (segment.selectedSegmentIndex == 2) {
mapView.mapType = MKMapTypeHybrid;
}
}
// When the view loads
- (void)viewDidLoad
{
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
[self.view insertSubview:mapView atIndex:0];
// Create the region
MKCoordinateRegion myRegion;
// Center
CLLocationCoordinate2D center;
center.latitude = Northern_Ireland_Latitude;
center.longitude = Northern_Ireland_Longitude;
// Create the Span
MKCoordinateSpan span;
span.latitudeDelta = The_Span;
span.longitudeDelta = The_Span;
myRegion.center = center;
myRegion.span = span;
// Set our map view
[mapView setRegion:myRegion animated:YES];
NSMutableArray *locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
MapViewAnnotation *myAnn;
//Premiership
// Pin to show Ballymena United F.C.
myAnn = [[MapViewAnnotation alloc] init];
location.latitude = Ballymena_Latitude;
location.longitude = Ballymena_Longitude;
myAnn.coordinate = location;
myAnn.title = #"Ballymena United F.C.";
myAnn.subtitle = #"The Showgrounds";
[locations addObject:myAnn];
// Championship 1
// Pin to show Ards F.C.
myAnn = [[MapViewAnnotation alloc] init];
location.latitude = Ards_Latitude;
location.longitude = Ards_Longitude;
myAnn.coordinate = location;
myAnn.title = #"Ards F.C.";
myAnn.subtitle = #"Clandeboye Park";
[locations addObject:myAnn];
// Championship 2
// Pin to show Annagh United F.C.
myAnn = [[MapViewAnnotation alloc] init];
location.latitude = Annagh_Latitude;
location.longitude = Annagh_Longitude;
myAnn.coordinate = location;
myAnn.title = #"Annagh United F.C.";
myAnn.subtitle = #"Tandragee Road";
[locations addObject:myAnn];
[self->mapView addAnnotations:locations];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[PlaceMark class]]) {
MKPinAnnotationView *annotationView =
(MKPinAnnotationView *)[myMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation
reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
UIImageView *imvLeft = [[UIImageView alloc] init];
//Set Image
[annotationView setLeftCalloutAccessoryView:imvLeft];
return annotationView;
}
return nil;
}

unable to display custom Annotations on the map in iPhone

I am trying to add annotations on my mapview but I am not able to add them. Can someone suggest me where I am doing wrong? Code: Code to add the map:
mapview = [[MKMapView alloc] initWithFrame:CGRectMake(10, 175, 300, 268)];
mapview.delegate = self;
mapview.userInteractionEnabled = TRUE;
[mapview setZoomEnabled:TRUE];
[mapview setScrollEnabled:TRUE];
mapview.showsUserLocation = TRUE;
[self.view addSubview:mapview];
//adding annotations in another method:
for (id annotation in mapview.annotations) {
[mapview removeAnnotation:annotation];
}
for(int i =0;i<arrEventList.count;i++){
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = [[NSString stringWithFormat:#"%#",[(NSDictionary*)[arrEventList objectAtIndex:i] objectForKey:#"lat"]] floatValue];
theCoordinate.longitude = [[NSString stringWithFormat:#"%#",[(NSDictionary*)[arrEventList objectAtIndex:i] objectForKey:#"lng"]] floatValue];
MyLocation *annotation = [[[MyLocation alloc] initWithName:[(NSDictionary*)[arrEventList objectAtIndex:i] objectForKey:#"event"] address:[(NSDictionary*)[arrEventList objectAtIndex:i] objectForKey:#"place"] coordinate:theCoordinate] autorelease];
[mapview addAnnotation:annotation];
//[annotations addObject:myAnno.annotation];
}
// delegate method:
- (MKAnnotationView *) mapView: (MKMapView *) mapView viewForAnnotation: (id<MKAnnotation>) annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyLocation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image=[UIImage imageNamed:#"annotation.png"];//here we use a nice image instead of the default pins
return annotationView;
}
return nil;
}
Above delegate method is only called for self location but it is not called for other annotations that I want to add.
Can someone point me to my mistakes
#interface MyLocation : NSObject <MKAnnotation> {
NSString *_name;
NSString *_address;
CLLocationCoordinate2D _coordinate;
}
#property (copy) NSString *name;
#property (copy) NSString *address;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate;
#end
//Mylocation class:
#implementation MyLocation
#synthesize name = _name;
#synthesize address = _address;
#synthesize coordinate = _coordinate;
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate {
if ((self = [super init])) {
_name = [name copy];
_address = [address copy];
_coordinate = coordinate;
}
return self;
}
- (NSString *)title {
if ([_name isKindOfClass:[NSNull class]])
return #"Unknown charge";
else
return _name;
}
- (NSString *)subtitle {
return _address;
}
I found the problem. My code is correct. The values of latittude and longitudes were some how interchanged. My mistake but I have corrected it now

iPhone: How to draw line between two points on MapKit?

I have Latitude and Longitude of two points and Want to Draw line between these two points with Pin on MapKit.
I have googled but Could not find some suitable solution because the one I found was drawing overlay with array of Data points but I do not have any array of points between these two points.
Just two points and want to draw line between these two points.
Please help.
First make your view controller implement the MKMapViewDelegate protocol and declare the properties you will need:
#property (nonatomic, retain) MKMapView *mapView; //this is your map view
#property (nonatomic, retain) MKPolyline *routeLine; //your line
#property (nonatomic, retain) MKPolylineView *routeLineView; //overlay view
then in viewDidLoad (for example, or wherever you initialize)
//initialize your map view and add it to your view hierarchy - **set its delegate to self***
CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] = CLLocationCoordinate2DMake(lat1, lon1);
coordinateArray[1] = CLLocationCoordinate2DMake(lat2, lon2);
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible
[self.mapView addOverlay:self.routeLine];
then implement the MKMapViewDelegate's method -(MKOverlayView *)mapView:viewForOverlay:
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 5;
}
return self.routeLineView;
}
return nil;
}
You can adjust the code to fit your need, but it's pretty much straight forward for 2 or more points.
Please See this tutorial to draw polyline or route in mkmapview
1>Draw route using mapkit
2>From versions above ios4.0 You can use MKOverlayPathView See Apple Docs
Sample code :-
create PolyLine:-
-(void) loadRoute
{
NSString* filePath = [[NSBundle mainBundle] pathForResource:#”route” ofType:#”csv”];
NSString* fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray* pointStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
MKMapPoint northEastPoint;
MKMapPoint southWestPoint;
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * pointStrings.count);
for(int idx = 0; idx < pointStrings.count; idx++)
{
NSString* currentPointString = [pointStrings objectAtIndex:idx];
NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]];
CLLocationDegrees latitude = [[latLonArr objectAtIndex:0] doubleValue];
CLLocationDegrees longitude = [[latLonArr objectAtIndex:1] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKMapPoint point = MKMapPointForCoordinate(coordinate);
if (idx == 0) {
northEastPoint = point;
southWestPoint = point;
}
else
{
if (point.x > northEastPoint.x)
northEastPoint.x = point.x;
if(point.y > northEastPoint.y)
northEastPoint.y = point.y;
if (point.x < southWestPoint.x)
southWestPoint.x = point.x;
if (point.y < southWestPoint.y)
southWestPoint.y = point.y;
}
pointArr[idx] = point;
}
self.routeLine = [MKPolyline polylineWithPoints:pointArr count:pointStrings.count];
_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
free(pointArr);
}
Display PoluLine :-
[self.mapView addOverlay:self.routeLine];
Adding the overlay alone will not render anything on the map. Your MKMapViewDelegate implementation must return an overlay for this route you’ve just added as simply adding won't help .
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay
{
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine)
{
//if we have not yet created an overlay view for this overlay, create it now.
if(nil == self.routeLineView)
{
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
}
overlayView = self.routeLineView;
}
return overlayView;
}
#import <MapKit/MapKit.h>
- (void)viewDidLoad
{
[mapview setDelegate:self];
mapview.showsUserLocation = YES;
}
- (CLLocationCoordinate2D)coordinateWithLocation:(NSDictionary*)location
{
double latitude = [[location objectForKey:#"lat"] doubleValue];
double longitude = [[location objectForKey:#"lng"] doubleValue];
return CLLocationCoordinate2DMake(latitude, longitude);
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateSpan span = MKCoordinateSpanMake(0.005, 0.005);
MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.location.coordinate, span);
[mapview setRegion:region];
[mapview setCenterCoordinate:userLocation.coordinate animated:YES];
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%#&sensor=true", mapview.userLocation.location.coordinate.latitude, mapview.userLocation.location.coordinate.longitude, #"24.1620661,72.394131"];
//http://maps.googleapis.com/maps/api/directions/json?origin=23.030000,72.580000&destination=23.400000,72.750000&sensor=true
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"%#",url);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSError *error = nil;
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *routes = [result objectForKey:#"routes"];
NSLog(#"%#",routes);
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSDictionary *end_location = [leg objectForKey:#"end_location"];
NSLog(#"dDDDDDD>>>>>>%#",leg);
double latitude = [[end_location objectForKey:#"lat"] doubleValue];
double longitude = [[end_location objectForKey:#"lng"] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = coordinate;
point.title = [leg objectForKey:#"end_address"];
point.subtitle = #"I'm here!!!";
[self.mapview addAnnotation:point];
NSArray *steps = [leg objectForKey:#"steps"];
int stepIndex = 0;
CLLocationCoordinate2D stepCoordinates[1 + [steps count] + 1];
stepCoordinates[stepIndex] = userLocation.coordinate;
for (NSDictionary *step in steps) {
NSDictionary *start_location = [step objectForKey:#"start_location"];
stepCoordinates[++stepIndex] = [self coordinateWithLocation:start_location];
if ([steps count] == stepIndex){
NSDictionary *end_location = [step objectForKey:#"end_location"];
stepCoordinates[++stepIndex] = [self coordinateWithLocation:end_location];
}
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count:1 + stepIndex];
[mapview addOverlay:polyLine];
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake((userLocation.location.coordinate.latitude + coordinate.latitude)/2, (userLocation.location.coordinate.longitude + coordinate.longitude)/2);
}];
}
then implement the MKMapViewDelegate's method -(MKOverlayView *)mapView:viewForOverlay:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor colorWithRed:204/255. green:45/255. blue:70/255. alpha:1.0];
polylineView.lineWidth = 1;
return polylineView;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *annotaionIdentifier=#"annotationIdentifier";
MKPinAnnotationView *aView=(MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotaionIdentifier ];
if (aView==nil) {
aView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotaionIdentifier];
aView.pinColor = MKPinAnnotationColorRed;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
// aView.image=[UIImage imageNamed:#"arrow"];
aView.animatesDrop=TRUE;
aView.canShowCallout = YES;
aView.calloutOffset = CGPointMake(-5, 5);
}
return aView;
}
First of all Add frame work
1 Foundation.framework
2 CoreGraphics.framework
3 CoreLocation.framework
4 MapKit.framework
Then create nsobject file Like see.... TrailsMap.h File
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface TrailsMap : NSObject<MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *image;
NSString *subtitle;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString *title;
#property (nonatomic,copy) NSString *image;
#property (nonatomic,copy) NSString *subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord;
TrailsMap.m
#import "TrailsMap.h"
#implementation TrailsMap
#synthesize coordinate,title,image,subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord{
self = [super init];
if (self) {
coordinate = coord;
}
return self;
}
Now Create coding in mainview Please see..
ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController<MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *MapView;
#property (nonatomic, retain) MKPolyline *routeLine;
#property (nonatomic, retain) MKPolylineView *routeLineView;
-(void)LoadMapRoute;
#end
Finally create coding in mainview.m file
ViewController.m
#import "ViewController.h"
#import "TrailsMap.h"
#interface ViewController ()
{
NSData *alldata;
NSMutableDictionary *data1;
NSMutableArray *RouteLocation;
NSMutableArray *RouteName;
}
#end
#implementation ViewController
#synthesize MapView,routeLine,routeLineView;
- (void)viewDidLoad
{
[super viewDidLoad];
RouteName = [[NSMutableArray alloc] initWithObjects:#"Ahmedabad",#"Rajkot", nil];
RouteLocation = [[NSMutableArray alloc] initWithObjects:#"23.0300,72.5800",#"22.3000,70.7833", nil];
[self LoadMapRoute];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
//-------------------------------------
// ************* Map ******************
//-------------------------------------
-(void)LoadMapRoute
{
MKCoordinateSpan span = MKCoordinateSpanMake(0.8, 0.8);
MKCoordinateRegion region;
region.span = span;
region.center= CLLocationCoordinate2DMake(23.0300,72.5800);
// Distance between two address
NSArray *coor1=[[RouteLocation objectAtIndex:0] componentsSeparatedByString:#","];
CLLocation *locA = [[CLLocation alloc] initWithLatitude:[[coor1 objectAtIndex:0] doubleValue] longitude:[[coor1 objectAtIndex:1] doubleValue]];
NSArray *coor2=[[RouteLocation objectAtIndex:1] componentsSeparatedByString:#","];
CLLocation *locB = [[CLLocation alloc] initWithLatitude:[[coor2 objectAtIndex:0] doubleValue] longitude:[[coor2 objectAtIndex:1] doubleValue]];
CLLocationDistance distance = [locA distanceFromLocation:locB];
NSLog(#"Distance :%.0f Meters",distance);
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=true", [RouteLocation objectAtIndex:0],[RouteLocation objectAtIndex:1] ];
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
alldata = [[NSData alloc] initWithContentsOfURL:url];
NSError *err;
data1 =[NSJSONSerialization JSONObjectWithData:alldata options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&err];
if (err)
{
NSLog(#" %#",[err localizedDescription]);
}
NSArray *routes = [data1 objectForKey:#"routes"];
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSArray *steps = [leg objectForKey:#"steps"];
int stepIndex = 0;
CLLocationCoordinate2D stepCoordinates[[steps count]+1 ];
for (NSDictionary *step in steps)
{
NSDictionary *start_location = [step objectForKey:#"start_location"];
double latitude = [[start_location objectForKey:#"lat"] doubleValue];
double longitude = [[start_location objectForKey:#"lng"] doubleValue];
stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude);
if (stepIndex==0)
{
TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]];
point.title =[RouteName objectAtIndex:0];
point.subtitle=[NSString stringWithFormat:#"Distance :%.0f Meters",distance];
[self.MapView addAnnotation:point];
}
if (stepIndex==[steps count]-1)
{
stepIndex++;
NSDictionary *end_location = [step objectForKey:#"end_location"];
double latitude = [[end_location objectForKey:#"lat"] doubleValue];
double longitude = [[end_location objectForKey:#"lng"] doubleValue];
stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude);
TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]];
point.title = [RouteName objectAtIndex:1];
point.subtitle=[NSString stringWithFormat:#"Distance :%.0f Meters",distance];
[self.MapView addAnnotation:point];
}
stepIndex++;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count: stepIndex];
[MapView addOverlay:polyLine];
[MapView setRegion:region animated:YES];
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor colorWithRed:204/255. green:45/255. blue:70/255. alpha:1.0];
polylineView.lineWidth = 5;
return polylineView;
}
If You want to set multiple pin in map then just add this code.
Annotaion is Objectfile.
-(void)LoadMultiplePin
{
RouteName = [[NSMutableArray alloc] initWithObjects:#"Ahmedabad",#"Rajkot",#"Limdi", nil];
RouteLocation = [[NSMutableArray alloc] initWithObjects:#"23.0300,72.5800",#"22.3000,70.7833",#"22.5728,71.8114", nil];
MKCoordinateSpan span = MKCoordinateSpanMake(2.9, 2.9);
MKCoordinateRegion region;
region.span = span;
region.center= CLLocationCoordinate2DMake(22.5728,71.8114);
int cnt=RouteLocation.count;
for (int p=0 ; p<cnt ; p++ )
{
NSArray *coor=[[RouteLocation objectAtIndex:p] componentsSeparatedByString:#","];
CLLocationCoordinate2D location=CLLocationCoordinate2DMake([[coor objectAtIndex:0] doubleValue],[[coor objectAtIndex:1] doubleValue]);
Annotaion *point=[[Annotaion alloc] initWithLocation:location];
point.title =[RouteName objectAtIndex:p];
[Map addAnnotation:point];
}
[Map setRegion:region animated:YES];
}
By using this code You can easily Drope two pin and draw line between that two Pin
Enjoy Happy Coding...:)
I took the great answer from #graver and did this for Swift 3:
// Called from viewDidLoad
func setupMap() {
mapView.delegate = self
// BusStop implements the MKAnnotation protocol, I have an array of them
let routeCoordinates = busStops.map({ $0.coordinate })
let routeLine = MKPolyline(coordinates: routeCoordinates, count: routeCoordinates.count)
mapView.setVisibleMapRect(routeLine.boundingMapRect, animated: false)
mapView.add(routeLine)
}
// MARK: MKMapViewDelegate
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let polyline = overlay as? MKPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: polyline)
polylineRenderer.strokeColor = .blue
polylineRenderer.lineWidth = 3
return polylineRenderer
}
return MKOverlayRenderer(overlay: overlay)
}
I have created demo in swift with continue update location on map with polyline.
Please follow below steps :
1) Create new project and set up required things.
2) Go to project target->Build Phases -> Link Binary with Libraries and add
MapKit.framwork, CoreLocation.framework.
3) Go to sotryboard and add mapview and linkup with your viewcontroller.
4) Add properties and delegates that i am providing code below.
ViewController.Swift
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController,CLLocationManagerDelegate,MKMapViewDelegate{
#IBOutlet weak var mapView:MKMapView!
var locationManager: CLLocationManager!
var routeArr:[CLLocationCoordinate2D] = []
var isStarted:Bool = false
// MARK:- Life cycle
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
locationManager.startMonitoringSignificantLocationChanges()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
// user activated automatic authorization info mode
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined || status == .denied || status == .authorizedWhenInUse {
// present an alert indicating location authorization required
// and offer to take the user to Settings for the app via
// UIApplication -openUrl: and UIApplicationOpenSettingsURLString
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
}
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
mapView.delegate = self
mapView.showsUserLocation = true
mapView.mapType = MKMapType(rawValue: 0)!
mapView.userTrackingMode = MKUserTrackingMode(rawValue: 2)!
}
// MARK:- Button Actions
#IBAction func startBtnClick(_ sender: Any) {
isStarted = true
}
#IBAction func endBtnClick(_ sender: Any) {
isStarted = false
routeArr.removeAll()
}
// MARK:- LocationManager Delegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
if isStarted == true {
if locations.count > 0 {
let newLocation:CLLocationCoordinate2D = (location?.coordinate ?? nil)!
routeArr.append(newLocation)
DispatchQueue.main.async {
if self.routeArr.count > 2 {
let route:[CLLocationCoordinate2D] = [self.routeArr[self.routeArr.count - 2] ,self.routeArr.last!]
print(route)
let polyline = MKPolyline(coordinates: route, count: route.count)
self.mapView.addOverlay(polyline)
}
}
}
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if (overlay is MKPolyline) {
let pr = MKPolylineRenderer(overlay: overlay)
pr.strokeColor = UIColor.red
pr.fillColor = .green
pr.lineWidth = 5
return pr
}else {
return MKOverlayRenderer()
}
}
}
Run your project and click on start button for tracking and you can see polyline on map. If you click on stop button then it will stop to draw polyline.
Thankyou
pass your address cordination
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps? output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
// NSString* apiUrlStr = #"http://maps.google.com/maps?output=dragdir&saddr=40.769264,-73.958995&daddr=47.286522,-122.312932";
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:nil];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[NSMutableArray alloc] init];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:loc];
}
return array;
}
-(void) updateRouteView:(UIColor *)clr {
CGContextRef context =CGBitmapContextCreate(nil,routeView.frame.size.width,routeView.frame.size.height,8,4 * routeView.frame.size.width,CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, clr.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
You can draw lines in map using MKPolyline.
See this link
http://spitzkoff.com/craig/?p=136
ALSO:
https://github.com/kishikawakatsumi/MapKit-Route-Directions
http://cloudmade.com/
These are all tutorials and open source libraries which you can easily refer to. Currently MapKit does not support this feature...
here you must calculate the route with its latitude and longtitude and then draw the poly line on MapView........
I do this things in my app....i draw route on mapview with all information....
here if you MapKit and also use RagexKitLite then its too simple for you just get Demo of RagexKitLite....
Get full code:https://github.com/javedmultani16/MapKitWithPolyLine
Draw line like:
directionsRequest.transportType = MKDirectionsTransportType.automobile
//Draw polyline by using MKRoute so it follows the street roads...
for (k, item) in arrayarrayPlacemarks.enumerated() {
if k < (arrayarrayPlacemarks.count - 1) {
directionsRequest.source = item
directionsRequest.destination = arrayarrayPlacemarks[k+1]
let directions = MKDirections(request: directionsRequest)
directions.calculate { (response:MKDirections.Response!, error: Error!) -> Void in
if error == nil {
self.locRoute = response.routes[0] as? MKRoute
let geodesic:MKPolyline = self.locRoute!.polyline
self.mapView.addOverlay(geodesic)
}
}
}
}
Delegate method :
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay.isKind(of: MKPolyline.self){
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.fillColor = UIColor.blue
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 2
return polylineRenderer
}
return MKOverlayRenderer(overlay: overlay)
}

MKMapView not showing on device

I have a little problem and i dont know why is it happening.
My map view is woking fine in the simulator but on the real device I only see the pin on the gray area and the "google" logo. It's like the images cant be loaded, it look like when you zoom in and you wait for the view to draw around the square.
Here is my code, I would appreciate any help
#import "Maps.h"
#import "RootViewController.h"
#implementation AddressAnnotation
#synthesize coordinate;
-(NSString *) subtitle{
return #"327 Anzac Parade, Wodonga, Victoria, Australia";
}
-(NSString *) title{
return #"Blazing Stump";
}
-(id)initWithCoordinate:(CLLocationCoordinate2D) c{
coordinate = c;
NSLog(#"%f,%f",c.latitude, c.longitude);
return self;
}
#end
#implementation Maps
-(CLLocationCoordinate2D) addressLocation{
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://maps.google.com/maps/geo?q=327%20Anzac%20Parade,%20Wodonga,%20Victoria,%20Australia&output=csv&key=ABQIAAAAZs2zFXiuKBFeLpPgSfgMjBTHxw17-t8q3X3AgrE9NufATyE8MRRmwlyLMPtOSzliJQntEtaZ7T-Rww"]
encoding:NSUTF8StringEncoding error:nil];
NSArray *listItems = [locationString componentsSeparatedByString:#","];
double latitude = -36.139226;
double longitude = 146.911454;
if ([listItems count] >=4 && [[listItems objectAtIndex:0] isEqualToString:#"200"]){
latitude = [[listItems objectAtIndex:2] doubleValue];
longitude = [[listItems objectAtIndex:3] doubleValue];
}else {
//some error
}
CLLocationCoordinate2D location;
location.latitude = latitude;
location.longitude = longitude;
return location;
}
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) 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;
}
- (void)viewDidLoad {
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.2;
span.longitudeDelta=0.2;
CLLocationCoordinate2D location = [self addressLocation];
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];
[super viewDidLoad];
}
- (void)dealloc {
[super dealloc];
[viewController release];
}
have you made sure the map delgate has been set? Make sure you add the delagate to the header and on the view did load mapkit.delagte=self;
Dan

How to show multiple pin annotation in map?

I m showing a pin annotation statically, but i want to do it dynamically to show a lot of pins on map with title and subtitle.
Thx in advance.
I have an array of dictionaries with have two objects lat, long and i am doing this -
if ([resultArray count])
{
for (int i =0; i < [resultArray count]; i++)
{
NSDictionary *dict = [resultArray objectAtIndex:i];
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = [[dict objectForKey:#"lat"] floatValue];
region.center.longitude = [[dict objectForKey:#"long"] floatValue];
region.span.longitudeDelta = 70.0f;
region.span.latitudeDelta = 70.0f;
MyAnnotations *ann = [[MyAnnotations alloc] init];
ann.title = #"title";
ann.coordinate = region.center;
[mapView addAnnotation:ann];
}
}
//
// MyAnnotation.h
//
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
//
// MyAnnotation.m
//
#import "MyAnnotation.h"
#implementation MyAnnotation
#synthesize coordinate,title,subtitle;
-(void)dealloc
{
[title release];
[subtitle release];
[super dealloc];
}
#end
use this delegate for callout -
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id )annotation
{
MKPinAnnotationView *pinView = nil;
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton addTarget:self action:#selector(infoButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = infoButton;
[defaultPinID release];
return pinView;
}