viewForAnnotation didn't get called (iOS noob) - ios

I know this question has been asked by others before and i have read them in this forum previously, but I have tried all the proposed approach without luck so far so I decided to post this question.
I have this piece of code below which is meant to change the pin icon on MKMapView. However the viewForAnnotation function doesn't even seem to get called by the MKMapView. People said that they got some problems with delegating the function to the file's owner which can be done by dragging the map view in .xib file to the file owner or defining myMap.delegate = self. I have done both ways but still get nothing.
Really appreciate for any help for my problem, thanks.
CODE:
- (MKPinAnnotationView*)myMap:(MKMapView*)myMap viewForAnnotation:(id<MKAnnotation>)annotation{
MKPinAnnotationView *pin = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:#"CustomPin"];
UIImage *icon = [UIImage imageNamed:#"bustour.png"];
UIImageView *iconView = [[UIImageView alloc] initWithFrame:CGRectMake(8,0,32,37)];
if(icon == nil)
NSLog(#"image: ");
else
NSLog(#"image: %#", (NSString*)icon.description);
[iconView setImage:icon];
[pin addSubview:iconView];
pin.canShowCallout = YES;
pin.pinColor = MKPinAnnotationColorPurple;
return pin;
}
DELEGATION

Your delegate method is named incorrectly as myMap:viewForAnnotation:.
The viewForAnnotation delegate method must be named mapView:viewForAnnotation: like this:
- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id < MKAnnotation >)annotation
{
//code goes here...
}
The map view will look for that exact method name.
If not found, it won't call it and will create a default red pin instead.
You can change the name of the internal parameters but not the method name.
For example, this would also be ok:
- (MKAnnotationView *)mapView:(MKMapView *)myMap
viewForAnnotation:(id < MKAnnotation >)annotation
{
//code goes here...
}

import bellow class in your .h class..
#import <MapKit/MapKit.h>
and also add MKMapViewDelegate in your this class like bellow...
#interface PTAViewController : UIViewController<MKMapViewDelegate>{
///...... your code..
}
#end

As I understand, you setting outlet, not delegate. To set delegate do like that:

Related

Custom MKAnnotationView expandable without callout

I want to create custom MKAnnotationView (with image) without a callout, but expandable after touch. Here is what i have in mind:
1) First the MKAnnotation looks like this:
2) Then after tap on it this should expand and looks like this:
I've started with customing MKAnnotationView and have a class:
#interface CustomPinAnnotation : NSObject <MKAnnotation>
The class have method:
-(MKAnnotationView*)annotationView {
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:self reuseIdentifier:#"AnnotationIdentifier"];
annotationView.enabled = YES;
annotationView.image = [[UIImage imageNamed:#"star"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
return annotationView;
}
And what i try to do is set a customView as a subview to the MKAnnotationView, but when i don't set The image it will not responding (this is pretty logical after i've think about it), but got the feeling that I'm doing something very nasty here, and should be a way to override MKAnnotationView somehow.
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
enemyAnnotationView.image = [UIImage imageNamed:#"firstImage.png"];
}
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
enemyAnnotationView.image = [UIImage imageNamed:#"SecondImage.png"];
}
Try like this first method is for the View for annotation that time your first image will be appears,
Second method will run when user select annotation

iOS trouble accessing property of MKAnnotation

I can't seem to access a custom MKAnnotation property inside of mapView:viewForAnnotation delegate method. As I understand it, the method takes annotations as values. I'm trying to target the properties of each annotation that gets passed in.
Code
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
//This actually returns a proper coordinate
NSLog(#"%f", annotation.coordinate.latitude);
//This gives me an error: Property 'annotationMarker' not found on object of type '__strong id<MKAnnotation>'
NSLog(#"%#", annotation.annotationMarker);
MKAnnotationView *testPin = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
testPin.image = [UIImage imageNamed:[[testArray objectAtIndex:1]annotationMarker]];
return testPin;
}
I thought maybe the custom property wasn't set correctly, but I'm able to log the property values for these annotations in other parts of the code.
Am I making some kind of syntax error? Does this delegate method strip out custom properties somehow?
You need to cast to your custom MKAnnotation-conformant class, e.g.
CustomAnnotation *customAnnotation = (CustomAnnotation *)annotation;
NSLog(#"%#", customAnnotation.annotationMarker);

MKAnnotationView is losing reference to MKAnnotation

In an app I'm working on, users are directed to push a button to drop MKAnnotations onto the map. They will drop 2 or 3 pins, each of which is saved to an #property when the pin is added in didAddAnnotationViews because I need a reference to it later, and I need to know which pin it is - pin 1, 2, or 3 (the order in which they are dropped).
I'm using a custom MKAnnotation and MKAnnotationView class to add a few NSStrings to each annotation, I'm not sure if that's important or not.
I'm creating 3 properties like this:
#property (nonatomic, strong) CustomAnnotationView *ann1;
#property (nonatomic, strong) CustomAnnotationView *ann2;
#property (nonatomic, strong) CustomAnnotationView *ann3;
Here is my didAddAnnotationViews:
- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views
{
for(MKAnnotationView *view in views)
{
if(![view.annotation isKindOfClass:[MKUserLocation class]])
{
CustomAnnotationView *newAnnView = (CustomAnnotationView*)view;
if(newAnnView.type == CustomType1)
{
ann1 = newAnnView;
}
else if(newAnnView.type == CustomType2)
{
ann2 = newAnnView;
}
else if(newAnnView.type == CustomType3)
{
ann3 = newAnnView;
}
}
}
}
Also, here's my viewForAnnotation method:
- (MKAnnotationView *)mapView:(MKMapView *)pMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if([annotation class] == MKUserLocation.class)
{
return nil;
}
CustomAnnotationView *annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"WayPoint"];
annotationView.canShowCallout = YES;
annotationView.draggable = YES;
[annotationView setSelected:YES animated:YES];
[annotationView setRightCalloutAccessoryView:customCalloutButton];
return annotationView;
}
Now, eventually, I need to save the coordinates of these annotations, and here's where things go wrong. Sometimes, but only once in a while, ann1.annotation.coordinate.latitude and ann1.annotation.coordinate.longitude are both 0.0 (this happens with ann1, ann2, or ann3, just using ann1 for example purposes)! Why is this happening? I have a feeling it has something to do with an object reference issue since the MKAnnotationView is still intact, but the annotation is cleared out. Maybe it's bad that I'm assigning the reference with ann1 = newAnnView? Am I supposed to use viewForAnnotation?
Does anyone see something I'm doing wrong?
UPDATE
I looked over my MKAnnotation subclass and I noticed that while I am defining a coordinate property according to the docs, I was not #synthesizing it in my implementation file. I have now added that and I haven't been able to replicate the issue yet...if this ends up being the "fix", I'm still very confused why my code would have worked most of the time without the #synthesize. Maybe I didn't actually fix it, and I'm setting myself up for disappointment later.
I don't think you;re supposed to use didAddAnnotationViews like that. Usually the flow is as follows:
Create an MKAnnotation, or an instance of your subclass of it
Assign the strings you mentioned
Call [mapView addAnnotation:myAnnotation]
In viewForAnnotation create an MKAnnotationView (or CustomAnnotationView( based on the annotation provided as a parameter
When you need to save the coordinates you can either loop through the mapView.annotations array, or if you have kept thre3 variables called ann1, ann2, ann3 could save them one by one.
Of course if you've found a better way or this doesn't fit something else in your app you don't need to use it, but this is the only flow I have seen thus far.

MapKit pin not displaying leftCalloutAccessoryView

I am following the iOS 5 version of Paul Hegarty's lecture on ios app developing, and I am working on assignment 5.
So basically I need to display a bunch of images on a map with the data provided from Flickr.
I got the pins working and displaying title and subtitles, however, when I try to put a UIImageView as the leftCalloutAccessoryView, it is not working.
So I set map view controller as the delegate of its mapView in viewDidLoad and it conforms to the MKMapViewDelegate protocol.
And I implemented the following two methods:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *aView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"MapVC"];
if (!aView) {
aView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"MapVC"];
aView.canShowCallout = YES;
aView.leftCalloutAccessoryView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
}
aView.annotation = annotation;
[(UIImageView *)aView.leftCalloutAccessoryView setImage:nil];
return aView;
}
and
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
UIImage *image = [self.delegate mapViewController:self imageForAnnotation:view.annotation];
[(UIImageView *)view.leftCalloutAccessoryView setImage:image];
}
However, when I click on a pin, it only shows title and subtitle. I am not sure what is going on since at this step basically all of my code are similar to his example in the video and I'm not sure what I am missing.
Thanks for your help!
---------------------------------Update:----------------------------------
I figured out my problem.
The problem is that I was segueing into the mapViewController, and I was adding the annotations in prepareForSegue, however, the mapView is an IBOutlet for the controller and it is not set yet in prepareForSegue, so basically I need to update my mapView again with the annotations passed to the controller in viewDidLoad, this indeed solved the problem.
Hopefully this will help anyone out there with similar problem!
I solved the problem myself, see the update part in question.

How to get location from map pin in iOS

I am using the MKMapView object and I am able to create pins and place them on the map. What I am trying to do now is get the information back from the pin. For example in my
- (MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation (id<MKAnnotation>)annotation
I create my pins and set them on the map. I am also creating buttons to use when a user clicks on the pin. All that works well and good. Now my question is when that button is clicked how do I get information from that clicked pin? Below is a small sample code of how I currently have it setup. Any advice would be greatly appreciated.
- (MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"location"];
annView.pinColor = MKPinAnnotationColorRed;
annView.animatesDrop = YES;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
UIButton* callout = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[callout addTarget:self action:#selector(loadDetails:) forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = callout;
return annView;
}
- (void)loadDetails:(id)sender
{
//TODO: Get pin coordinates or address and match it back to an array of available address to show details in a new view
}
Any advice is greatly appreciated
Instead of setting the target of your callout, respond to the delegate method
mapView:annotationView:calloutAccessoryControlTapped:
The annotationView will have an annotation property with the coordinate.
You should create a class that derives from MKPinAnnotationView that has a property of id<MkAnnotationView>. During the method above, create this new object instead of the MKPinAnnotationView and set the id<MKAnnotation> property to the annotation passed in.

Resources