Can't get different pin image using plist file - ios

I use plist file to store annotation data that have Name, Address, Coordinates and Icon (pin image name) strings in dictionary. I need to show my annotations on map with pin image depending on Icon string in plist. I loop my annotation dictionaries but it show on map pin image from first dict on all my pins.
My code:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
NSString *path = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
for(path in dict){
NSString *theCategory;
theCategory = [NSString stringWithFormat:#"%#", path];
NSLog(#"%#", path);
NSArray *anns = [dict objectForKey:theCategory];
pinView.image = [UIImage imageNamed:[[anns objectAtIndex:0] objectForKey:#"Icon"]];
}
pinView.canShowCallout=YES;
return pinView;
}
My plist file construction:
What it show to me:

The viewForAnnotation delegate method will get called for each annotation added.
The for-loop you have inside that method will run the same way for each annotation. All the for-loop ends up doing (every time for each annotation) is setting pinView.image to the last item read by the for-loop. This happens to be the first item in the first dictionary in the plist.
You need to instead set pinView.image to the Icon of the item that is for the current annotation that viewForAnnotation is being called for (ie. the annotation parameter that is passed). So you could keep the for-loop and check if the item matches annotation and only then set pinView.image (and then break out of the for-loop).
But it's not a good idea to constantly be re-reading and looping through a plist in that delegate method. It's better to make Icon a property of your annotation class, set the property when creating the annotation (you are probably looping through the plist to create the annotations in the first place), and then just use that property directly from the annotation object itself in the viewForAnnotation delegate method.
Assuming you have some custom annotation class, add Icon as a property:
#interface MyAnnotationClass : NSObject<MKAnnotation>
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, copy) NSString *icon; //<---and #synthesize it in .m
Then in the place where you loop through the plist to create the annotations, set the icon property just like you are setting the title property:
ann.title = [item objectForKey:#"Name"];
ann.icon = [item objectForKey:#"Icon"];
Finally, in viewForAnnotation, you can read the icon property directly from the annotation. But first, you should check that annotation is of your custom class type (so the user location blue dot is not affected and to be reasonably sure annotation will have the property you're about to access):
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if (![annotation isKindOfClass:[MyAnnotationClass class]])
{
// Note "!" sign in front of above condition.
// Return nil (default view) if annotation is
// anything but your custom class.
return nil;
}
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *pinView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
// Create an MKAnnotationView instead of MKPinAnnotationView
// because we are setting a custom image.
// Using MKPinAnnotationView sometimes overrides custom image
// with the built-in pin view.
if (pinView == nil)
{
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
pinView.canShowCallout = YES;
}
else
pinView.annotation = annotation;
MyAnnotationClass *myAnn = (MyAnnotationClass *)annotation;
pinView.image = [UIImage imageNamed:myAnn.icon];
// May want to check if myAnn.icon is blank (length == 0)
// (OR if pinView.image is still nil after setting)
// and show some default image in that case otherwise
// annotation will be invisible.
return pinView;
}
By the way, in your plist file, Test3 has no Icon setting.

Related

dynamically change leftCalloutAccessoryView based on the MKAnnotationView that is selected

I have an array of images, that are associated with each Annotation on my map. I can statically add an image to the leftCalloutAccessoryView but I am unsure how to make this dynamic. I hope its clear what I am asking. Each annotation has its own individual image that I want to display but I am unsure of how to reference the image in the following method;
- (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id <MKAnnotation>)annotation
{
if([annotation isKindOfClass:[MKUserLocation class]])
return nil;
NSString *annotationIdentifier = #"PinViewAnnotation";
MyAnnotationView *pinView = (MyAnnotationView *) [mv dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
if (!pinView)
{
pinView = [[MyAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
pinView.canShowCallout = YES;
UIImageView *houseIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Icon"]];//static image
[houseIconView setFrame:CGRectMake(0, 0, 30, 30)];
pinView.leftCalloutAccessoryView = houseIconView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
My array "self.sandwiches" contains Sandwich objects that have a name (NSString) and an imageName ('NSString').
Im looking for a solution where I can get the index of the pin that is selected, similar to a UITableView where you can get its index, and access it from the array using indexPath.row.
My Annotation class;
.h
#import
#import
#import
#interface SandwichAnnotation : NSObject<MKAnnotation>
#property (nonatomic,assign) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString * title;
#property (nonatomic,copy) NSString * subtitle;
#end
.m
#import "SandwichAnnotation.h"
#implementation SandwichAnnotation
#synthesize coordinate,title,subtitle;
#end
In viewForAnnotation, rather than "getting the index of the pin" (which would work but is less efficient here than with a UITableView), I suggest adding the data required to the annotation class itself.
This way, the data is more self-contained and the code in the delegate method or elsewhere doesn't need to worry, know, or be kept in sync with where or what kind of structure the annotation object is stored in. As long as you have a reference to the annotation object, you will immediately have all the data needed for that annotation (or at least it will contain references to the related data within itself).
The viewForAnnotation delegate method provides a reference to the annotation object it needs a view for (the annotation parameter). It's typed generically as id<MKAnnotation> but it is actually an instance of the exact type that was created (either SandwichAnnotation by you or MKUserLocation by the map view).
One option is to make the parent Sandwich class itself implement MKAnnotation and eliminate the SandwichAnnotation class. This way, no searching or references are needed at all since the annotation parameter will actually be a Sandwich.
However, you may want to keep a separate class for your annotation objects (which is fine). In this case, you can add a reference to the parent object(s) in the annotation class. Example:
#interface SandwichAnnotation : NSObject<MKAnnotation>
#property (nonatomic,assign) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString * title;
#property (nonatomic,copy) NSString * subtitle;
#property (nonatomic,retain) Sandwich * whichSandwich; // <-- add reference
#end
When creating a SandwichAnnotation, set the reference to which Sandwich the annotation is for:
for (Sandwich *currentSandwich in self.sandwiches) {
SandwichAnnotation *sa = [[SandwichAnnotation alloc] init...];
sa.coordinate = ...
sa.title = ...
sa.whichSandwich = currentSandwich; // <-- set reference
[mapView addAnnotation:sa];
}
Finally, in viewForAnnotation, if annotation is of type SandwichAnnotation, set the leftCalloutAccessoryView:
- (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id <MKAnnotation>)annotation
{
if (! [annotation isKindOfClass:[SandwichAnnotation class]]) {
//If annotation is not a SandwichAnnotation, return default view...
//This includes MKUserLocation.
return nil;
}
//At this point, we know annotation is of type SandwichAnnotation.
//Cast it to that type so we can get at the custom properties.
SandwichAnnotation *sa = (SandwichAnnotation *)annotation;
NSString *annotationIdentifier = #"PinViewAnnotation";
MyAnnotationView *pinView = (MyAnnotationView *) [mv dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
if (!pinView)
{
pinView = [[MyAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
pinView.canShowCallout = YES;
//Here, just initialize a blank UIImageView ready to use.
//Set image below AFTER we have a dequeued or new view ready.
UIImageView *houseIconView = [[UIImageView alloc] init];
[houseIconView setFrame:CGRectMake(0, 0, 30, 30)];
pinView.leftCalloutAccessoryView = houseIconView;
}
else
{
pinView.annotation = annotation;
}
//At this point, we have a dequeued or new view ready to use
//and pointing to the correct annotation.
//Update image on the leftCalloutAccessoryView here
//(not just when creating the view otherwise an annotation
//that gets a dequeued view will show an image of another annotation).
UIImageView *houseIconView = (UIImageView *)pinView.leftCalloutAccessoryView;
NSString *saImageName = sa.whichSandwich.imageName;
UIImage *houseIcon = [UIImage imageNamed: saImageName];
if (houseIcon == nil) {
//In case the image was not found,
//set houseIcon to some default image.
houseIcon = someDefaultImage;
}
houseIconView.image = houseIcon;
return pinView;
}

Different custom image for each pin

This may sound like a generic question but I've only found answers if I want the same image for all my pins, which i don't.
That's how i'm working right now :
I have all my locations in an array of Locations (custom class with long, lat, name, pin name).
in the viewdidLoad I loop that array and create my pins with every object found, see following code :
for(int i = 0 ; i<[_locationList count] ; i++)
{
Location *item = [_locationList objectAtIndex:i];
CLLocationCoordinate2D coordinate;
coordinate.latitude = item.locationLatitude;
coordinate.longitude = item.locationLongitude;
NSString *title = item.locationName;
CustomAnnotation* ann = [CustomAnnotation new];
ann.name = title;
ann.coordinate = coordinate;
ann.pinName = [NSString stringWithFormat:#"pin%i.png",item.idPin];
[self.map addAnnotation:ann];
}
This is pretty straight forward, part from the CustomAnnotation class, which is the following code :
#interface CustomAnnotation : MKPointAnnotation <MKAnnotation>{
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *description;
#property (nonatomic, retain) NSString *pinName;
#end
This is all from stuff i've seen around the internet, and I kinda believe it's all correct up to that point.
In my mind, i'm still creating very classic pins, they just have one more property (pinName), which is why it's coming from the custom class.
Now, in the viewForAnnotation, i have absolutly NO IDEA how to tell it to get that pinName and use it.
- (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.
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = // I wanted to write annotation.pinName But it's just not that.
pinView.calloutOffset = CGPointMake(0, 32);
}else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
What am I missing? I'm obviously doing something wrong but i jsut can't figure it out, and i'm still quite confused with the differences between MKAnnotationsView & MKPointAnnotation & MKPinAnnotation, ...
More info : the pin names are " pinX.png ", X being a number between 1 and 12. I just want to use that name so the program can find it in the ressources where the picture lies.
Since your annotations are of type CustomAnnotation, it would be more accurate to check if the annotations are of that kind instead of MKPointAnnotation.
Then, casting the annotation parameter to your custom class will let you easily access the custom properties in it like this:
CustomAnnotation *ca = (CustomAnnotation *)annotation;
pinView.image = [UIImage imageNamed:ca.pinName];
However, because the image can be different for each annotation, you should set it after the annotation view has been created or dequeued (not only in the if (!pinView) block -- otherwise an annotation could end up re-using the view from another annotation no longer visible and the wrong image will show).
The updated method would look like this:
- (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:[CustomAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.calloutOffset = CGPointMake(0, 32);
//NOTE:
//If the calloutOffset needs to be different for each image,
//then this line should also be set below with the image.
}
else {
pinView.annotation = annotation;
}
//Set image on view AFTER we have a new or dequeued view
//because image is based on each annotation...
CustomAnnotation *ca = (CustomAnnotation *)annotation;
pinView.image = [UIImage imageNamed:ca.pinName];
//Might want to check that the UIImage is not nil
//in case pinName is invalid since that would result in
//an invisible annotation view. If the UIImage is nil,
//set pinView.image to some default image.
return pinView;
}
return nil;
}
For the confusion about the differences between the MapKit classes, see:
Should I use MKAnnotation, MKAnnotationView or MKPinAnnotation?. Even though that question is tagged MonoTouch, it still applies.
MKMapView, animateDrop? may also help.

custom data variables in mkannotation

I have a map view controller (UIViewController, MKMapView), with its delegate (HCIResultMapViewController).
I wish to have following functionality in this part.
1). I wish to use my custom made NSObject , so that I can associate others details along with the basic entities like title, subtitle etc.
Hence according to my needs I coded as following
In HCIResultMapViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_houseList = [[_resultList objectForKey:#"result"] objectForKey:#"listings"];
// NSLog([_houseList description]);
int i = 0;
for (NSDictionary *house in _houseList) {
HCIAnnotationViewController *annotation = [[HCIAnnotationViewController alloc]
initwithHouse:house];
[_mapView addAnnotation:annotation];
// NSLog(#"asdjhasdjsajdhaksdjghasdasdjahsdahskvdka");
self.currIdentifier = i;
i++;
}
[_mapView setShowsUserLocation:NO];
}
The other delegate functions
-(void) mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
for (NSObject<MKAnnotation> *annotation in _mapView.selectedAnnotations) {
NSLog(#"hellomaster");
NSLog(annotation.title);
if ([annotation isKindOfClass:[HCIAnnotationViewController class]]) {
NSLog(#"hellomaster");
}
}
The last one
-(MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
NSString *identifier = #"currIdentifier";
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.tag = self.currIdentifier;
// Create a UIButton object to add on the
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[annotationView setRightCalloutAccessoryView:rightButton];
/*
UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[leftButton setTitle:annotation.title forState:UIControlStateNormal];
[annotationView setLeftCalloutAccessoryView:leftButton];
*/
return annotationView;
}
But I see that the class equivalence fails. Can you tell me what I'm doing wrong?
I think what I want, in simple words, is, how can I send some data (NSDictionary*) along with a annotation such that I can retrieve it whenever I want?
Please dont tag this as repeated question or so. I have tried many questions, googling etc. but couldn't find a suitable solution for this.
Here You can also set NSMutableDictionary instand of NSString.
Create custom AnnotationView:
#import <MapKit/MapKit.h>
#interface AnnotationView : MKPlacemark
#property (nonatomic, readwrite, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, strong) NSString *title; //Here You cam set `NSMutableDictionary` instand of `NSString`
#property (nonatomic, strong) NSString *subtitle; //Here You cam set `NSMutableDictionary` instand of `NSString`
#end
And in .m file
#import "AnnotationView.h"
#implementation AnnotationView
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate addressDictionary:(NSDictionary *)addressDictionary
{
if ((self = [super initWithCoordinate:coordinate addressDictionary:addressDictionary]))
{
self.coordinate = coordinate;
}
return self;
}
#end
// Use Annotation Add #import "AnnotationView.h" in your relevant .m file:
CLLocationCoordinate2D pCoordinate ;
pCoordinate.latitude = LatValue;
pCoordinate.longitude = LanValue;
// Create Obj Of AnnotationView class
AnnotationView *annotation = [[AnnotationView alloc] initWithCoordinate:pCoordinate addressDictionary:nil] ;
annotation.title = #"I m Here";
annotation.subtitle = #"This is Sub Tiitle";
[self.mapView addAnnotation:annotation];
I couldn't find exact way to implement custom data variables or the reason why my class equivalence fails. But I figured out a way to over come this kind of situation. This might be redundant in method, but still works like a charm.
So the idea is to use the tagging system in control button. I observed that every time I send a message to my map view to add a annotation it immediately calls my viewforannotation method. Since I'm iterating through an array, I maintained a index global pointer, with which I set tag of the control button. Later when the button is clicked, I retrieve the tag and use it to get the object I want.
Anyone else have any alternative or direct solution, please do post.

MKPinAnnotationView loses pinColor after MKMapView zoom in

I have a MKMapView with a lot of annotation pins defined from a parser xml; thats my code:
-(IBAction)LoadAnnotation:(id)sender {
RXML element ...
RXML iterate....
[myMap removeAnnotations:myMap.annotations];
annotation.title = // NSString from RXML parser
annotation.subtitle = // NSString from RXML parser
myValue = // float value from RXML parser
[mymap addAnnotation:annotation];
}
and then
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation2 {
MKPinAnnotationView *pinView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation2 reuseIdentifier:#"MyPin"];
if ( myValue > 0 && myValue < 10) {
pinView.canShowCallout = YES;
pinView.pinColor = MKPinAnnotationColorRed;
pinView.animatesDrop=YES;
return pinView;
}
else if ( myValue > 10 && myValue < 20 ) {
pinView.canShowCallout = YES;
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop=YES;
return pinView;
}
pinView.canShowCallout = YES;
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.animatesDrop=YES;
return pinView;
}
All right, when my MKMapView is loaded, I can see title annotations, subtitle annotations and all the pins with different colours.
But if I scroll and zoom IN the map at a certain level, then zoom OUT again, all the pins become PURPLE. What's happening there?
I have tried also using same "annotation" (id) in the two methods (and not "annotation" and "annotation2"), but I have no result.
Is there a way to avoid that and keep pinColors after map scroll and zoom?
The viewForAnnotation delegate method isn't necessarily called only once for each annotation nor is it guaranteed to be called in the order that you add the annotations. It's also called for the user location (blue dot) if you set showsUserLocation to YES.
When you zoom or pan the map, the map view will call the delegate method (again) as annotations come back into view. At that time, your myValue will have no relevance to the annotation the map is requesting a view for.
Instead of using a class-level ivar, add myValue as a property of your annotation class and set it along with the title and subtitle before you call addAnnotation:
annotation.title = // NSString from RXML parser
annotation.subtitle = // NSString from RXML parser
annotation.myValue = // float value from RXML parser
^^^^^^^^^^^
Then in viewForAnnotation, use the myValue property from the annotation parameter instead of an ivar. This way, the delegate method is always using information specific to the annotation it is requesting a view for:
if ( ! [annotation isKindOfClass:[MyCustomAnnotationClass class]])
{
return nil; //return a default view if not your custom class
}
//cast annotation to custom class so we can get the custom property...
MyCustomAnnotationClass *myPin = (MyCustomAnnotationClass *)annotation;
//use the custom property in the annotation instead of ivar...
if (myPin.myValue > 0 && myPin.myValue < 10) {
....
Changing the name of the annotation parameter to annotation2 is not necessary.
Unrelated but you should be implementing annotation view re-use by using dequeueReusableAnnotationViewWithIdentifier (search for it in the SDK or on SO). It can help with performance if there are a lot of annotations.
Your MyAnnotation class should look like this:
#interface MyAnnotation : NSObject <MKAnnotation> {
float myValue;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate; //<-- add
#property (nonatomic, copy) NSString *title; //<-- add
#property (nonatomic, copy) NSString *subtitle; //<-- add
#property (nonatomic, assign) float myValue;
#end
#implementation MyAnnotation
#synthesize coordinate; //<-- add
#synthesize title; //<-- add
#synthesize subtitle; //<-- add
#synthesize myValue;
#end
The place where you add the annotation should look like this:
MyAnnotation *annotation = [[MyAnnotation alloc] init];
annotation.title = someTitle; // NSString from RXML parser
annotation.subtitle = someSubTitle; // NSString from RXML parser
annotation.myValue = someValue; // someValue from RXML parser
[mapView addAnnotation:annotation];
Above, someValue is whatever myValue was in your original ViewController.
Also, in viewForAnnotation, change annotation2 back to annotation and don't forget to put MKPinAnnotationView *pinView =[[MKPinAnnotationView alloc] init... before the MyAnnotation *myPin = ... line.

ios-mapkit, strange behavior with custom image annotations

I've written some code for showing annotations with custom images in a mapview.
My mapview delegate implements this method to customize annotation when they are put in the map:
- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation:(id<MKAnnotation>) annotation {
if ([annotation isKindOfClass:[Station class]]) {
Station *current = (Station *)annotation;
MKPinAnnotationView *customPinview = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil];
if([[current type] compare:FONTANELLA]==NSOrderedSame)
customPinview.pinColor = MKPinAnnotationColorPurple;
else{
int test=current.bici;
if(test==0)
customPinview.image = [UIImage imageNamed:#"bicimir.png"];
else if(test<4)
customPinview.image = [UIImage imageNamed:#"bicimi.png"];
else if(test>=4)
customPinview.image = [UIImage imageNamed:#"bicimig.png"];
}
customPinview.animatesDrop = NO;
customPinview.canShowCallout = YES;
return customPinview;
}
else{
NSString *identifier=#"MyLocation";
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
return annotationView;
}
}
The problem is a strange behavior when I long click on a custom annotation on the map:
The image change and the default red pin is shown.
Why this behavior? And How can I avoid it?
When you want to use a custom image for an annotation view, create a generic MKAnnotationView instead of an MKPinAnnotationView.
The MKPinAnnotationView really likes to display its default image which is a pin.
Rearrange the logic a bit so that for FONTANELLA, it creates an MKPinAnnotationView but for the rest an MKAnnotationView.
Also, you should really implement annotation view re-use for all cases (and the last else part doesn't make sense since nothing is done if the dequeue doesn't return anything--you could just do return nil; instead).
inside .h file
#interface AddressAnnotation : NSObject<MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *mPinColor;
}
#property (nonatomic, retain) NSString *mPinColor;
#end
in .m file
#implementation AddressAnnotation
#synthesize coordinate mPinColor;
- (NSString *)pincolor{
return mPinColor;
}
- (void) setpincolor:(NSString*) String1{
mPinColor = String1;
}
-(id)initWithCoordinate:(CLLocationCoordinate2D) c{
coordinate=c;
NSLog(#"%f,%f",c.latitude,c.longitude);
return self;
}
#end
inside .m class file
- (MKAnnotationView *) mapView:(MKMapView *)mapView1 viewForAnnotation:(AddressAnnotation *) annotation{
UIImage *anImage=[[UIImage alloc] init];
MKAnnotationView *annView=(MKAnnotationView*)[mapView1 dequeueReusableAnnotationViewWithIdentifier:#"annotation"];
if(annView==nil)
{
annView=[[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annotation"] autorelease];
}
if([annotation.mPinColor isEqualToString:#"green"])
{
anImage=[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Google pin green.png" ofType:nil]];
}
else if([annotation.mPinColor isEqualToString:#"red"])
{
anImage=[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Google pin red.png" ofType:nil]];
}
else if([annotation.mPinColor isEqualToString:#"blue"])
{
anImage=[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Google pin blue.png" ofType:nil]];
}
annView.image = anImage;
return annView;
}

Resources