MKAnnotation - How to display a button on the annotation bubble - ios

I am trying to use a map to set annotation in it, where the user wants to put it.
I want the user to touch the screen where he wants to put a pin, and by clicking on the appeared pin, he can be redirected to another view where he can put details.
I followed several tutorials to make the button appear on the right of the callout, but this does not work...
Here is my code :
MAPpin is the NSObject file :
MAPpin.h :
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MAPpin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
MAPpin.m :
#import "MAPpin.h"
#implementation MAPpin
#synthesize coordinate,title,subtitle, mapView;
#end
And my view controller :
MAPwelcomeViewController.h
#import <UIKit/UIKit.h>
#import <MAPKit/MKAnnotation.h>
#import "MAPAppDelegate.h"
#import "MAPpin.h"
#interface MAPwelcomeViewController : UIViewController <MKMapViewDelegate>
- (IBAction)longpress:(UILongPressGestureRecognizer *)sender;
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#end
and the MAPwelcomeViewController.m :
#import "MAPwelcomeViewController.h"
#import "MAPpin.h"
#import "myAnnotation.h"
#define METERS_PER_MILE 1609.344
#interface MAPwelcomeViewController ()
#end
#implementation MAPwelcomeViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
{
[super viewDidLoad];
_mapView.showsUserLocation = YES;
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//1
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 40.740848;
zoomLocation.longitude= -73.991145;
// 2
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 0.3*METERS_PER_MILE, 0.3*METERS_PER_MILE);
[self.mapView setRegion:viewRegion animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#pragma mark -MapView Delegate Methods
//6
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
//7
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
//8
static NSString *identifier = #"myAnnotation";
MKPinAnnotationView * annotationView = (MKPinAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!annotationView)
{
//9
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.pinColor = MKPinAnnotationColorPurple;
annotationView.animatesDrop = YES;
annotationView.canShowCallout = YES;
}else {
annotationView.annotation = annotation;
}
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
}
- (IBAction)longpress:(UILongPressGestureRecognizer *)sender {
CGPoint point = [sender locationInView:self.mapView];
CLLocationCoordinate2D loccoord = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
myAnnotation *ann = [[myAnnotation alloc] initWithCoordinate:loccoord title:#"Test"];
[self.mapView addAnnotation:ann];
}
#end
So following (http://www.codigator.com/tutorials/mapkit-tutorial-for-ios-beginners/"this links") I added the following method :
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
But when I run the app, no button is showing... what do you think I am doing wrong ?
Thanks in advance,
regards !

Most likely, the map view's delegate is not set so the viewForAnnotation delegate method never gets called and the map view creates a default red pin with no callout accessory button.
In the storyboard, right-click on the map view control and connect its delegate outlet to the View Controller.
Or, in code, in the viewDidLoad method, before setting showsUserLocation, set the delegate programmatically:
self.mapView.delegate = self;
Some unrelated comments...
Once the button is appearing, to handle the user tapping the callout accessory, a recommended approach is to implement the calloutAccessoryControlTapped delegate method. See the answer to MKAnnotationView Push to View Controller when DetailDesclosure Button is Clicked for an example.
A separate issue I should point out is that the gesture handler method isn't checking the gesture recognizer's state before creating an annotation. So what can happen is multiple pins can get created while the user is still doing a single long press. To avoid this, add a check like this at the top of the longpress: method:
if (sender.state != UIGestureRecognizerStateBegan)
{
return;
}
Another unrelated thing is that the code is creating an annotation of type myAnnotation by doing myAnnotation alloc but the annotation class you've shown is of type MAPpin.
Finally, adding an MKMapView as an IBOutlet and property in the MAPpin class is completely unnecessary. You should remove it from there before it leads to confusion.

Related

MapView Application

I have written simple mapView application.It is showing two kind of problems.
1- Execution is stopping on Thread 1: signal SIGABRT error.
2- This function is showing compile time error .
- (IBAction)findMe:(id)sender {
If( [[toggleButton titleForState:UIControlStateNormal] isEqualToString:#"Find Me"] )
{
[toggleButton setTitle:#"Hide Me" forState:UIControlStateNormal];
mapView.showsUserLocation=YES;
}
else
{
[toggleButton setTitle:#"Find Me" forState:UIControlStateNormal];
mapView.showsUserLocation=NO;
}
}
How to remove these error ?
I want put coordinates of more then one location in my code i want to show loc.png icon on map corresponding to those coordinates how i can accomplish this task?
You can see the sample project from this link: https://drive.google.com/open?id=0B5pNDpbvZ8SnRmNFS0pjVnJFWHc
You are getting compile time error for 3 reasons:
1) The "If" you are using in if-else condition should be "if" i.e lowercase.
2). You have an IBOutlet connect to findMe button in storyboard which do not exist in your view controller. So either remove it or add it.
3)You are using MKMapView but you didn't added the MapKit Framework in "Link Binaries" in build phases option of your project.
Please do all these steps to have your code compiled & executed error free.
Answer to your query:
I want put coordinates of more then one location in my code i want to show loc.png icon on map corresponding to those coordinates how i can accomplish this task?
Here is the code for ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate>
#end
Here is the code for ViewController.m
#import "ViewController.h"
#import "MyAnnotation.h"
#import <MapKit/MapKit.h>
#interface ViewController ()
#property (strong, nonatomic) IBOutlet MKMapView *myMapView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// setup the map view, delegate and current location
[self.myMapView setDelegate:self];
self.myMapView.mapType = MKMapTypeStandard;
CLLocationCoordinate2D myLocation = CLLocationCoordinate2DMake(25.085130,-77.331428);
[self.myMapView setCenterCoordinate:myLocation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(myLocation, 2000, 2000);
region.center = self.myMapView.centerCoordinate;
self.myMapView.showsUserLocation = YES;
[self.myMapView setRegion:region animated:YES];
[self dropPins];
}
-(void)dropPins {
NSMutableArray *annotationArray = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location1 = CLLocationCoordinate2DMake(25.085130, -77.331428);
MyAnnotation *annotation1 = [[MyAnnotation alloc] initWithCoordinates:location1 image:#"loc.png"];
[annotationArray addObject:annotation1];
[self.myMapView addAnnotations:annotationArray];
[annotationArray removeAllObjects];
CLLocationCoordinate2D location2 = CLLocationCoordinate2DMake(25.085130, -77.336428);
MyAnnotation *annotation2 = [[MyAnnotation alloc] initWithCoordinates:location2 image:#"loc.png"];
[annotationArray addObject:annotation2];
[self.myMapView addAnnotations:annotationArray];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyAnnotation class]])
{
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.myMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else
{
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = NO;
if([[(MyAnnotation *)annotationView.annotation image] isEqualToString:#"pin1.png"])
annotationView.image = [UIImage imageNamed:#"loc.png"];
if([[(MyAnnotation *)annotationView.annotation image] isEqualToString:#"pin2.png"])
annotationView.image = [UIImage imageNamed:#"loc.png"];
return annotationView;
}
return nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Add new files MyAnnotation.h/MyAnnotation.m
Here is the code for MyAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation>
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy, readonly) NSString *image;
-(id)initWithCoordinates:(CLLocationCoordinate2D) paramCoordinates
image:(NSString *) paramImage;
#end
Here is the code for MyAnnotation.m
#import "MyAnnotation.h"
#implementation MyAnnotation
-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates
image:(NSString *)paramImage
{
self = [super init];
if(self != nil)
{
_coordinate = paramCoordinates;
_image = paramImage;
}
return (self);
}
#end

Annotation Pin for current location not appearing

I was trying to utilise map kit to show my current location using MKMapView and its delegate method, didUpdateUserLocation but when I zoom in and comes really close, I would see multiple pins. Then after some suggestions I realised, every time, the location is updated the pin is re-created. So, I took my add annotation code out of the delegate method.
Here is my code-
#import "MapViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface MapViewController ()<MKMapViewDelegate, CLLocationManagerDelegate, UITextFieldDelegate> {
MKPointAnnotation *myAnnotation;
}
#property (nonatomic, strong) IBOutlet MKMapView *mapView;
#property (nonatomic, strong) IBOutlet UITextField *searchTextField;
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#implementation MapViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate=self;
self.mapView.showsUserLocation=YES;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
myAnnotation = [[MKPointAnnotation alloc]init];
myAnnotation.coordinate = self.mapView.userLocation.coordinate;
myAnnotation.title = #"Current Location";
[self.mapView addAnnotation:myAnnotation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark-
#pragma mark- MapView Delegate
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
#end
but now there is no pin.
=> MKMapView automatically places an annotation of class MKUserLocation when you set mapView.showsUserLocation = YES:
You can replace the default view for this annotation to whatever default annotation view you want by doing this in mapView:viewForAnnotation:
- (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
// replace the following with code to generate and return custom user position annotation view
return customAnnotationView;
}
//*** other code ***//
}
Dear you need to put your myAnnotation code outside your delegate method "didUpdateUserLocation"
Note : you need to make Annotation in viewDidLoad then use didUpdateUserLocation for update your coordinate
yes right if you do not want to display pin in mapview then keep out side of code or remove it whitch you have written in didUpdateUserLocation.

Set label or text field to annotation title

Edit: Original Statement:
I have a navigation controller embedded with a mapView on one view controller and it push segues into a second view controller by the use of a callout. The User hits the info key on the callout and they segue into the second view controller where they have to fill out a form. Once they hit the back key in the second view controller navigation bar, how would I link the first two lines of the form they filled out to be the title and subtitle of the pin?
Update: I've gone mad, because I have googled and re-made my XCode project to fulfill this one objective. I don't like to leave tasks uncompleted. I am getting nil for my string and text field when I return back towards the first view controller.
first view controller.h file
#import <UIKit/UIKit.h>
#import "mapKit/Mapkit.h"
#import "thePinsViewController.h"
#interface ViewController : UIViewController <MKMapViewDelegate, MKAnnotation, thePinsViewController> {
MKMapView *mapViewing;
MKPointAnnotation *annot;
}
#property(nonatomic, retain) IBOutlet MKMapView *mapViewing;
#end
first view controller.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize coordinate = _coordinate;
// This is your IBOutlet
#synthesize mapViewing;
// Initiate when the user holds the map to place a pin
- (void) addGestureRecognizerToMapView {
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
// User needs to press for [insert number in decimal format] seconds
lpgr.minimumPressDuration = 1.0;
[mapViewing addGestureRecognizer:lpgr];
}
// This method fires when you add a pin
- (void)handleLongPress:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateBegan) {
return;
}
CGPoint touchPoint = [gestureRecognizer locationInView: mapViewing];
CLLocationCoordinate2D touchMapCoordinate = [mapViewing convertPoint:touchPoint toCoordinateFromView:mapViewing];
annot = [[MKPointAnnotation alloc] init];
annot.title = #"a";
annot.subtitle = #"SubTitle";
annot.coordinate = touchMapCoordinate;
[mapViewing addAnnotation:annot];
}
// This is your manual callout box
// with a rightDisclosureButton embedded in it
- (MKAnnotationView *)mapView:(MKMapView *)sender viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#""];
// This gives the user permission to see or not see the callout box
annotationView.canShowCallout = YES;
// This is the info button in the callout box
UIButton *rightDisclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.rightCalloutAccessoryView = rightDisclosureButton;
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
thePinsViewController *scoobydoo = [[thePinsViewController alloc] init];
[self performSegueWithIdentifier:#"heylisten" sender:view];
scoobydoo.delegate = self;
}
- (void) didFirstFieldChange:(NSString*)newValue{
// Change your annotation title here
annot.title = newValue;
}
- (void) didSecondFieldChange:(NSString*)newValue{
// Change your annotation title here
annot.subtitle = newValue;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[mapViewing setDelegate:self];
[self addGestureRecognizerToMapView];
}
second view controller.h file
#import <UIKit/UIKit.h>
#protocol thePinsViewController <NSObject>
- (void) didFirstFieldChange:(NSString*)newValue;
- (void) didSecondFieldChange:(NSString*)newValue;
#end
#interface thePinsViewController : UIViewController
#property (nonatomic, weak) id<thePinsViewController> delegate;
#property(nonatomic, strong) IBOutlet UITextField *helloWorldTextField;
#property(nonatomic, strong) IBOutlet UITextField *helloWorldTextField2;
#property(nonatomic, strong) NSString *helloWorldString;
#end
second view controller.m file
#import "thePinsViewController.h"
#interface thePinsViewController ()
#end
#implementation thePinsViewController
#synthesize helloWorldTextField;
#synthesize helloWorldTextField2;
#synthesize helloWorldString;
- (void) firstFieldChanged{
if ( [self.delegate performSelector:#selector(didFirstFieldChange:)] ){
[self.delegate didFirstFieldChange:helloWorldTextField.text];
}
}
- (void) secondFieldChanged{
if ( [self.delegate performSelector:#selector(didSecondFieldChange:)] ){
[self.delegate didSecondFieldChange:helloWorldTextField2.text];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
helloWorldString = helloWorldTextField.text;
}
You should add a delegate pattern to pass the info from your second view controller back to your first view controller.
PinInformationViewController.h
#protocol PinInformationViewControllerProtocol <NSObject>
- (void) didFirstFieldChange:(NSString*)newValue;
- (void) didSecondFieldChange:(NSString*)newValue;
#end
#interface PinInformationViewController : UIViewController
#property (nonatomic, weak) id<PinInformationViewControllerProtocol> delegate;
#end
PinInformationViewController.m
- (void) firstFieldChanged{
if ( [self.delegate performSelector:#selector(didFirstFieldChange:)] ){
[self.delegate didFirstFieldChange:myTextField.text];
}
}
- (void) secondFieldChanged{
if ( [self.delegate performSelector:#selector(didSecondFieldChange:)] ){
[self.delegate didSecondFieldChange:myOtherTextField.text];
}
}
FirstViewController.m
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
pinInformationViewController *scoobydoo = [[pinInformationViewController alloc]init];
scoobydoo.delegate = self;
annot.title = scoobydoo.helloWorldString;
[self performSegueWithIdentifier:#"heylisten" sender:view];
}
- (void) didFirstFieldChange:(NSString*)newValue{
// Change your annotation title here
}
- (void) didSecondFieldChange:(NSString*)newValue{
// Change your annotation subtitle here
}

MKMapView with custom MKAnnotation

I've a MKMapView.
I want to put a custom MKAnnotation on my map.
They are some restaurant places. How can I do it?
My question is how can I make a custom MKAnnotation?
Thanks, guys.
First, let's define custom as meaning not simply title and subtitle. We want to change the size of the MKAnnotation and include some custom graphics.
There are two parts to an annotation you might want to customize:
MKAnnotation
MKAnnotationView
For the most basic MKAnnotation you would simply adopt the protocol and return nil for title and subtitle, but you could also carry a lot more information in your annotation for an extended callout upon tapping an accessory indicator. You can add all of the annotations to the MKMapView using addAnnotation: in viewDidLoad for example.
MKAnnotation Header
#interface CPAnnotation : NSObject <MKAnnotation> {
#private
CLLocationCoordinate2D _coordinate;
NSString *_title;
NSString *_subtitle;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, readonly, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
#end
MKAnnotation Implementation
#implementation CPAnnotation
#synthesize coordinate = _coordinate;
#synthesize title = _title;
#synthesize subtitle = _subtitle;
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
self = [super init];
if (self != nil) {
self.coordinate = coordinate;
}
return self;
}
- (NSString *)title {
return _title;
}
- (NSString *)subtitle {
return _subtitle;
}
#end
The next step is to customize the callout from the pin dropped. To do this you need to customize MKAnnotationView. According to Apple you shouldn't make a huge callout by default. They recommend a standard size callout that has a button to open a bigger one. They use the lowercase i in a blue circle icon. Those icons can be set via the view's leftCalloutAccessoryView and rightCalloutAccessoryView property. If you already adopted the MKMapViewDelegate protocol and set yourself as the MKMapView's delegate you will get the callback for viewForAnnotation:.
MKAnnotationView MKMapViewDelegate callback
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *const kAnnotationReuseIdentifier = #"CPAnnotationView";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:kAnnotationReuseIdentifier];
if (annotationView == nil) {
annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:kAnnotationReuseIdentifier] autorelease];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeInfoLight];
}
return annotationView;
}
You can further customize this in a custom view overriding the drawRect method, providing an image to the image property, or you could even implement an MKAnnotationView in a XIB. It is worth some experimentation.
Apple's WeatherAnnotationView Example illustrates overriding drawRect.
I had a case where I wanted something like a standard Pin annotation, but the designer wanted a custom graphic.
I wrote a subclass of MKAnnotationView to display the graphic. The only difference is that it overrides the standard class's image.
BlipAnnotationView.h
#import <MapKit/MapKit.h>
#interface BlipAnnotationView : MKAnnotationView
- (id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier;
#end
BlipAnnotationView.m
#import "BlipAnnotationView.h"
#implementation BlipAnnotationView
- (id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self) {
UIImage *blipImage = [UIImage imageNamed:#"blip.png"];
CGRect frame = [self frame];
frame.size = [blipImage size];
[self setFrame:frame];
[self setCenterOffset:CGPointMake(0.0, -7.0)];
[self setImage:blipImage];
}
return self;
}
#end
Then in the class that displays the map, I made the class implement the MKMapViewDelegate protocol. The mapView:viewForAnnotation: method creates a new instance of BlipAnnotationView if necessary.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
NSLog(#"mapView:%# viewForAnnotation:%#", mapView, annotation);
static NSString *const kAnnotationIdentifier = #"BlipMapAnnotation";
BlipAnnotationView *annotationView = (BlipAnnotationView *)
[mapView dequeueReusableAnnotationViewWithIdentifier:kAnnotationIdentifier];
if (! annotationView) {
annotationView = [[BlipAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:kAnnotationIdentifier];
}
[annotationView setAnnotation:annotation];
return annotationView;
}
Finally I set the class as the delegate of the map view in awakeFromNib:
- (void)awakeFromNib
{
[...]
[_theMapView setDelegate:self];
}
I didn't have to change the code that positioned the annotation at all:
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
[annotationPoint setCoordinate:[userLocation coordinate]];
[annotationPoint setTitle:label];
[_theMapView addAnnotation:annotationPoint];

Trouble changing color of the pin iOS MapKit

I'm having trouble changing the pinColor for an annotation in MapKit. When I don't try to implement the mapView:viewForAnnotation: method everything works (the annotation is added) but when I try to change the annotation view, the simulator crashes :
Here is the code :
MapViewController.h
#import "MapViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "Annotation.h"
#implementation MapViewController
#synthesize myMapView;
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
CLLocationCoordinate2D location;
location.longitude = 2.21;
location.latitude = 48.5;
MKCoordinateSpan span;
span.latitudeDelta = 1*(1 - 0);
span.longitudeDelta = 1*(1 - 0);
MKCoordinateRegion region;
region.span = span;
region.center = location;
[myMapView setRegion:region animated:NO];
[myMapView regionThatFits:region];
Annotation *someAnnotation =[[Annotation alloc] init];
[myMapView addAnnotation:someAnnotation];
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation:(id<MKAnnotation>) annotation {
MKPinAnnotationView *customPinview = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil] autorelease];
customPinview.pinColor = MKPinAnnotationColorGreen;
customPinview.animatesDrop = YES;
customPinview.canShowCallout = YES;
return customPinview;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
MapViewController.m
//
// MapViewController.h
// TestMap
//
// Created by Johan Ismael on 10/21/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface MapViewController : UIViewController<MKMapViewDelegate> {
#private
IBOutlet MKMapView *myMapView;
}
#property (nonatomic, retain) IBOutlet MKMapView *myMapView;
//- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation:(id<MKAnnotation>) annotation;
#end
Thanks in advance !!!
Note : MapViewController is declared as the delegate of the MapView in IB
In the viewForAnnotation method, the alloc is being done on MKAnnotationView instead of MKPinAnnotationView. It must be crashing with "unrecognized selector" because MKAnnotationView doesn't have a pinColor property. Change the alloc to:
MKPinAnnotationView *customPinview = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:nil] autorelease];

Resources