MKAnnotationView not showing up on the map - ios

I am trying to annotate my map with MKPointAnnotation, like this:
- (void)viewDidLoad
{
NSLog(#"RootViewController viewDidLoad");
[super viewDidLoad];
CLLocationCoordinate2D coord =
CLLocationCoordinate2DMake(54.903683,23.895435);
MKPointAnnotation *toyAnnotation = [[MKPointAnnotation alloc] init];
toyAnnotation.coordinate = coord;
toyAnnotation.title = #"Title";
toyAnnotation.subtitle = #"Subtitle";
[mapView addAnnotation:toyAnnotation];
[toyAnnotation release];
}
- (MKAnnotationView *)mapView:(MKMapView *)m
viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(#"RootViewController mapView: viewForAnnotation:");
NSLog(#"%#",annotation);
MKAnnotationView *pin = [[MKAnnotationView alloc]
initWithAnnotation:annotation
reuseIdentifier:nil];
pin.enabled = YES;
pin.canShowCallout = YES;
return [pin autorelease];
}
Pin fails to appear on the map. RootViewController is a delegate for mapView and thus mapView:viewForAnnotation: method gets called:
2011-11-24 15:04:03.808 App[2532:707] RootViewController mapView: viewForAnnotation:
2011-11-24 15:04:03.810 App[2532:707] <MKPointAnnotation: 0x1885c0>
What am I doing wrong and how to fix this issue?

In viewForAnnotation, create an MKPinAnnotationView instead of an MKAnnotationView (for which you have to set the image).
Although for a default pin annotation view, you don't need to implement the delegate method at all.

Related

Getting annotation pin tap event

I am loading the mapview as below, with MKAnnotationView added as subview in the mapview. I have added as subview, instead of addAnnotation, as I wanted the annotation view in the center all the time and the mapview to scroll under it.
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView addSubview:self.centerAnnotationView];
}
- (MKPointAnnotation *)centerAnnotaion
{
if (!_centerAnnotaion) {
_centerAnnotaion = [[MKPointAnnotation alloc] init];
_centerAnnotaion.title = #"Title";
}
return _centerAnnotaion;
}
- (MKPinAnnotationView *)centerAnnotationView
{
if (!_centerAnnotationView) {
_centerAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:self.centerAnnotaion
reuseIdentifier:#"centerAnnotationView"];
_centerAnnotationView.pinColor = MKPinAnnotationColorGreen;
_centerAnnotationView.canShowCallout = YES;
_centerAnnotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
return _centerAnnotationView;
}
I have the following questions.
Is it possible to get the default callout even when I haven't added the pin as annotation to the map view.
Is there a way that I could get - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view event working in my case.
Should I use the tap gesture to capture the tap on the annotation pin?

Getting MapKit animateDrop to work

Helloall in MapKit I can't figure out how to get the animateDrop animation to run, I'm using 1 viewController with both CoreLocation and MapKit running on it.
I read that I need to make sure I have set a delegate from the mapview to self in viewDidLoad which I have done and also to make sure I am using MKPinAnnotationView to get access to the animateDrop property, which I think I have done also?
I'm building for iOS8 also.
Any help would be great
//I'm not showing all code just showing some of the related parts of code below
.h
//I do set standard imports UIKit, CoreLocation, MapKit etc
#interface ViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate>
//I do set various properties related. CLLocationManager, CLLocation, MKMapView
.m
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate = self;
MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init];
myAnnotation.coordinate = CLLocationCoordinate2DMake(37.813186, 144.962979);
myAnnotation.title = #"My title";
myAnnotation.subtitle = #"My sub title";
[self.mapView addAnnotation:myAnnotation];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
//pinView.animatesDrop = YES;
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
Any help would be great

performing segue when a map annotation pin is tapped

I'm trying to perform a segue when a map annotation pin is tapped. Im using a custom annotation class if that makes a difference.
I've tried
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
NSLog(#"annotation selected");
[self performSegueWithIdentifier:#"mySegue" sender:self];
}
but my NSLog isnt running so I assume the method isnt getting called.
The only other things I've done are add the annotation pin to my map view and set my view controller as the map view delegate.
Here is how I added the annotation to the mapview
SPMapAnnotation *pin = [[SPMapAnnotation alloc] init];
pin.coordinate = spotLocation.coordinate;
pin.title = [spot objectForKey:#"spotName"];
[self.mapView addAnnotation:pin];
How can I make this work? That didSelectAnnotation method seems like it would make this easy to do but I'm not sure how it works.
Apparently I forgot I didnt allocate my mapView until viewDidAppear. Just needed to add
self.mapView.delegate = self;
after I alloc and inited it.
Implement following delegate method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *annotationView = nil;
if ([annotation isKindOfClass:[SPMapAnnotation class]])
{
annotationView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:#"Pin"];
if (annotationView == nil)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Pin"];
annotationView.canShowCallout = YES;
annotationView.animatesDrop = YES;
}
}
return annotationView;
}
as didSelectAnnotationView will not be called for standard annotation pin, you need to return MKAnnotationView for didSelectAnnotationView to be called.

MKAnnotationView not displayed when object creation is performed within a custom annotation class

Environment
Xcode: 5.0.2, Device: iPhone,
iOS: iOS 7
I am trying to use the mapView:viewForAnnotation: delegate method. Within this method, if I create the MKAnnotationView object, the pin gets displayed without any issue. Here is the working code:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[CustomeAnnotation class]])
{
// CustomeAnnotation *myLocation = (CustomeAnnotation *)annotation;
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"MyCustomAnnotation"];
if (annotationView == nil)
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"MyCustomAnnotation"];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
//annotationView.image = [UIImage imageNamed:#"park_icon"];
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
// annotationView = myLocation.createAnnotationView;
else
annotationView.annotation = annotation;
//return nil;
return annotationView;
}
else
return nil;
}
When I create a class method and move the MKAnnotationView object creation and property setting within the class method and I call it from the mapView:viewForAnnotation: delegate method, the pin does not appear.
Here is the code for the two methods in question (mapView:viewForAnnotation: and createAnnotationView):
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.mapView.delegate = self;
CLLocationCoordinate2D baysideParkCoordinates = CLLocationCoordinate2DMake(25.774407, -80.185797);
CustomeAnnotation *baysideParkAnnotation = [[CustomeAnnotation alloc] initWithTitle:#" Bayfront Park"
coordinate:baysideParkCoordinates];
[self.mapView addAnnotation:baysideParkAnnotation];
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[CustomeAnnotation class]])
{
CustomeAnnotation *myLocation = (CustomeAnnotation *)annotation;
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"MyCustomAnnotation"];
if (annotationView == nil)
annotationView = [myLocation createAnnotationView];
else
annotationView.annotation = annotation;
// return nil;
return annotationView;
}
else
return nil;
}
#end
The custom class
#import "CustomeAnnotation.h"
#implementation CustomeAnnotation
-(id)initWithTitle:(NSString *)newTitle coordinate:(CLLocationCoordinate2D) newCoordinate
{
self = [super init];
if (self)
{
self.title = newTitle;
self.coordinate = newCoordinate;
}
return self;
}
-(MKAnnotationView *)createAnnotationView
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:self reuseIdentifier:#"MyCustomAnnotation"];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
//annotationView.image = [UIImage imageNamed:#"park_icon"];
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
}
#end
The import statement for the CustomeAnnotation class is included in the ViewController.h file.
At this point I believe I am not passing back correctly the MKAnnotationView object back to the method call in the ViewController implementation file. Could anyone tell me what is it that I am doing wrong on the second set of code?
In the second set of code, in createAnnotationView, the annotation is not showing because it's not setting the image.
Note that an MKAnnotationView does not have a default image so if you don't set it, the annotation is invisible.
Uncomment the setting of the image (or create an MKPinAnnotationView instead).
The reason the first set of code works (even though it is also creating an MKAnnotationView) is because there's actually a small bug in the code:
MKAnnotationView *annotationView = [mapView dequeue...
if (annotationView == nil)
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] init...
//^^^^^^^^^^^^^^^^ Here, the code declares a NEW, LOCAL variable
// named annotationView but it has no connection to the
// annotationView declared outside the if-block.
Because the annotationView declared outside the if is never set, it stays nil and that's what the delegate method actually returns.
When you return nil from viewForAnnotation, the map view creates a default view for you (a red pin for your annotations, a blue dot for the user location).
To fix the first set of code, don't declare a new, local variable. Just set the variable:
MKAnnotationView *annotationView = [mapView dequeue...
if (annotationView == nil)
{
annotationView = [[MKAnnotationView alloc] init...
and don't forget to set the image (or create an MKPinAnnotationView instead).

iOS - MKMapView - Draggable Annotations

I have the annotation ready to go, but trying to figure out on how to make it draggable with my code:
-(IBAction) updateLocation:(id)sender{
MKCoordinateRegion newRegion;
newRegion.center.latitude = mapView.userLocation.location.coordinate.latitude;
newRegion.center.longitude = mapView.userLocation.location.coordinate.longitude;
newRegion.span.latitudeDelta = 0.0004f;
newRegion.span.longitudeDelta = 0.0004f;
[mapView setRegion: newRegion animated: YES];
CLLocationCoordinate2D coordinate;
coordinate.latitude = mapView.userLocation.location.coordinate.latitude;
coordinate.longitude = mapView.userLocation.location.coordinate.longitude;
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
[annotation setCoordinate: coordinate];
[annotation setTitle: #"Your Car is parked here"];
[annotation setSubtitle: #"Come here for pepsi"];
[mapView addAnnotation: annotation];
[mapView setZoomEnabled: YES];
[mapView setScrollEnabled: YES];
}
Thanks in advance!
To make an annotation draggable, set the annotation view's draggable property to YES.
This is normally done in the viewForAnnotation delegate method.
For example:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString *reuseId = #"pin";
MKPinAnnotationView *pav = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (pav == nil)
{
pav = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
pav.draggable = YES;
pav.canShowCallout = YES;
}
else
{
pav.annotation = annotation;
}
return pav;
}
If you need to handle when the user stops dragging and drops the annotation, see:
how to manage drag and drop for MKAnnotationView on IOS?
In addition, your annotation object (the one that implements MKAnnotation) should have a settable coordinate property. You are using the MKPointAnnotation class which does implement setCoordinate so that part's already taken care of.

Resources