问题
I want my annotations in two colors. For that I have used following code,
- (MKAnnotationView *)mapView:(MKMapView *)sender viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = @"MyLocation";
if ([annotation isKindOfClass:[PlaceMark class]]) {
MKPinAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
@try {
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation
reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
if([[nsCenterOrOffice objectAtIndex:z] isEqualToString:@"C"])
{
annotationView.pinColor = MKPinAnnotationColorRed;
}
else
{
annotationView.pinColor = MKPinAnnotationColorGreen;
}
}
}
@catch (NSException *exception) {
NSLog(@"nsCenterOrOffice exception = %@",exception);
}
return annotationView;
}
return nil;
}
But still I am not able to set desired color for desired annotation. Sometimes particular annotation pin color is red and sometimes it's green. I am not getting why this is happening. Can anybody help me ? Thanks...
I rework on my code..this is my updated code
MapAnnotation.h
#import <MapKit/MapKit.h>
#import <Foundation/Foundation.h>
@interface MapAnnotation : MKPointAnnotation
{
NSString *title;
NSString *subtitle;
int dealLnk;
float latitude;
float longitude;
CLLocationCoordinate2D coordinate;
}
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
@property (nonatomic, assign) int dealLnk;
@property (nonatomic, assign) float latitude;
@property (nonatomic, assign) float longitude;
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithTitle:(NSString *)ttl subTitle:(NSString *)subttl dealLink:(int)dealLnk latitude:(float)latitude longitude:(float)longitude andCoordinate:(CLLocationCoordinate2D)c2d;
@end
MapAnnotation.m
#import "MapAnnotation.h"
@implementation MapAnnotation
@synthesize title,subtitle,dealLnk,coordinate,latitude,longitude;
- (id)initWithTitle:(NSString *)ttl subTitle:(NSString *)subttl dealLink:(int)z latitude:(float)latitude1 longitude:(float)longitude1 andCoordinate:(CLLocationCoordinate2D)c2d {
title = ttl;
subtitle = subttl;
dealLnk =z;
coordinate = c2d;
longitude = longitude1;
latitude = latitude1;
return self;
}
@end
And this is my implementation file
-(void)startAddingAnnotation
{
@try {
CLLocationCoordinate2D annotationCoord;
z=0;
for (int i=0; i < [nslatitude count] ; i++,z++)
{
MapAnnotation *dealAnnotation = [[MapAnnotation alloc] init];
dealAnnotation.dealLnk = z;
annotationCoord.latitude = (CGFloat) [[nslatitude objectAtIndex:i] floatValue];
annotationCoord.longitude = (CGFloat)[[nslongitude objectAtIndex:i] floatValue];
dealAnnotation.coordinate = annotationCoord;
dealAnnotation.title = [nsCenterName objectAtIndex:i];
dealAnnotation.subtitle = [nsCenterAddress objectAtIndex:i];
NSLog(@"latitude = %f",dealAnnotation.latitude);
NSLog(@"longitude = %f",dealAnnotation.longitude);
NSLog(@"dealAnnotation.dealLnk = %d",dealAnnotation.dealLnk);
NSLog(@"dz = %d",z);
[mapView addAnnotation:dealAnnotation];
}
}
@catch (NSException *exception) {
NSLog(@"Exception = %@",exception);
}
cord.longitude = -112.05186;
cord.latitude = 33.46577;
MKCoordinateRegion region;
region.center = cord;
MKCoordinateSpan span = {.latitudeDelta = 1.0, .longitudeDelta = 1.0};
region.span = span;
[mapView setRegion:region];
}
#pragma mark - MapView_Delegate
- (MKAnnotationView *)mapView:(MKMapView *)sender viewForAnnotation:(id <MKAnnotation>)annotation {
MapAnnotation *annotation1 = (MapAnnotation *)annotation;
z = annotation1.dealLnk;
NSLog(@"annotation1.longitude = %f",annotation1.latitude);
NSLog(@"annotation1.longitude = %f",annotation1.longitude);
if(z<[nslatitude count])
{
MKAnnotationView *pinView = nil;
static NSString *defaultPinID = @"pin1";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation1 reuseIdentifier:defaultPinID];
pinView.canShowCallout = YES;
@try {
if([[nsCenterOrOffice objectAtIndex:z] isEqualToString:@"C"])
{
pinView.image = [UIImage imageNamed:@"flag1.png"];
}
else
{
pinView.image = [UIImage imageNamed:@"flag2.png"];
}
pinView.annotation = annotation1;
pinView.tag = [[nsCenterName objectAtIndex:z] intValue];
}
@catch (NSException *exception) {
NSLog(@"nsCenterOrOffice exception = %@",exception);
}
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[pinView setRightCalloutAccessoryView:rightButton];
return pinView;
}
else
{
return nil;
}
}
Now the problem is, all the annotations are pointing some different location. I am not getting why this is happening? Is der anything wrong in my code?
回答1:
The condition that determines the pin color is based on data outside of this delegate method and there is no guarantee that it will be in sync with when this delegate method is called for a particular annotation.
In this if
condition:
if([[nsCenterOrOffice objectAtIndex:z] isEqualToString:@"C"])
the z
variable is apparently some instance variable declared and set (probably right before adding an annotation) outside this delegate method.
Again, there is no guarantee that the viewForAnnotation
delegate method will be called immediately after an annotation is added. There is also no guarantee that the delegate method will be called only once for each annotation. So it's possible that the z
value does not correspond to the current annotation
that the delegate method is being called for.
It is very possible for the delegate method to be called well after addAnnotation
is called, that it will be called in a different order than the annotations were added, and that it will be called multiple times for each annotation (eg. if user pans or zooms the map and annotations come back into view).
To fix this, add the "is center or office" property to the Placemark
class itself and set that property when creating the annotation and before calling addAnnotation
. Then, in the viewForAnnotation
method, you can cast the annotation
parameter as a Placemark
and access the property to implement the condition. For example:
//where you create and add the annotation:
Placemark *pm = [[Placemark alloc...
pm.coordinate = ...
pm.title = ...
pm.centerOrOffice = [nsCenterOrOffice objectAtIndex:z];
[mapView addAnnotation:pm];
//in viewForAnnotation:
Placemark *myPlacemark = (Placemark *)annotation;
if ([myPlacemark.centerOrOffice isEqualToString:@"C"])
...
A separate, unrelated issue is that the annotation view creation logic is not quite right.
The code calls initWithAnnotation
twice and in actuality the second initWithAnnotation
never gets called since the first call will always succeed.
What you probably wanted was to first call dequeueReusableAnnotationViewWithIdentifier:
and then, if that returns nil
, call initWithAnnotation
.
When restructuring the code in viewForAnnotation
, be sure to put the code that sets the pinColor
outside the dequeue/init of the annotation view (eg. right before the return annotationView;
) to properly handle reused views.
回答2:
Your viewForAnnotation
is relying upon some external variables, nsCenterOrOffice
and z
. We certainly can't help you until you show us how you're setting those variables.
Regardless, this is not a prudent practice. Your viewForAnnotation
generally should rely solely upon properties of the annotation
, not external variables.
来源:https://stackoverflow.com/questions/17946302/ios-pin-color-issue-in-mapkit