Reputation: 51
I'm having great trouble figuring out what I'm doing wrong here...
I am adding annotations to my mapview through loops, but the annotation image is completely random every time... when I NSLog
the order, it's random - i'm not sure if that is the problem.
- (MKAnnotationView *)mapView:(MKMapView *)mapView1 viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if ([[annotation subtitle] isEqual:@"Bar"]) {
MKAnnotationView *view = nil;
view = [self.mapView dequeueReusableAnnotationViewWithIdentifier:@"myAnnotationIdentifier"];
if (!view) {
// Could not reuse a view ...
// Creating a new annotation view
view = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"myAnnotationIdentifier"];
view.enabled = YES;
view.canShowCallout = YES;
view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
view.image = [UIImage imageNamed:@"beer.png"];
}
return view;
}
else if ([[annotation subtitle] isEqual:@"Club"]) {
MKAnnotationView *view = nil;
view = [self.mapView dequeueReusableAnnotationViewWithIdentifier:@"myAnnotationIdentifier"];
if (!view) {
// Could not reuse a view ...
// Creating a new annotation view
view = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"myAnnotationIdentifier"];
view.enabled = YES;
view.canShowCallout = YES;
view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
view.image = [UIImage imageNamed:@"clubs.png"];
}
return view;
}
}
the view.image is totally random... either clubs.png
or beer.png
..
How do I make it correctly?
this is how I add the annotations:
- (void)barLoop {
for (int i = 0; i<barArray.count; i++) {
int index = [[barArray objectAtIndex:i]intValue];
NSString *lati = [[[self.usersLocationArray objectAtIndex:index]
valueForKeyPath:@"items.Latitude"]componentsJoinedByString:@""];
NSString *longi = [[[self.usersLocationArray objectAtIndex:index]
valueForKeyPath:@"items.Longitude"]componentsJoinedByString:@""];
NSString *barNavn = [[[self.usersLocationArray objectAtIndex:index] valueForKeyPath:@"items.Navn"]componentsJoinedByString:@""];
float latitude = [lati floatValue];
float longitude = [longi floatValue];
MKCoordinateRegion region = { {0.0, 0.0} , {0.0, 0.0} };
region.center.latitude = latitude;
region.center.longitude = longitude;
region.span.longitudeDelta = 0.20f;
region.span.latitudeDelta = 0.20f;
[mapView setRegion:region animated:NO];
CLLocationCoordinate2D location;
location.latitude = latitude;
location.longitude = longitude;
Annotation *ann = [[Annotation alloc]initWithPosition:location];
ann.title = barNavn;
ann.subtitle = @"Bar";
[self.mapView addAnnotation:ann];
}
}
thanks in advance :)
Upvotes: 2
Views: 1000
Reputation: 438232
You have two types of annotations, but you are only setting the image when the annotation is originally created. Thus, if an annotation for a bar scrolls off the map view and another annotation for a club scrolls on, it might reuse the bar's annotation view for the club.
There are two ways of fixing this:
Use different reuseIdentifier
parameters for each of the two types of annotation views; or
Set/reset the annotation view's image
regardless of whether your call to dequeueReusableAnnotationViewWithIdentifier
succeeded in returning a value or not.
Unrelated, but your viewForAnnotation
method should:
You might want to use isEqualToString
instead of isEqual
when checking for @"Bar"
vs @"Club"
.
Make sure to return nil
if neither of those if
clauses return true (this should never happen, but nonetheless you have a potential path in this routine in which you neglect to return any value). I would guess that this would have been brought to your attention if you ran the code through the static analyzer ("Analyze" on Xcode's "Product" menu).
A more subtle observation, but I'd probably not rely upon the annotation's subtitle
for determining which annotation view to employ, but rather either
have two annotation subclasses, one for bars and one for clubs; or
have a custom property in your existing Annotation
class that indicates whether it's a bar or club (and I'd probably use an enum
for that).
At some future date, you might want to use the callout's subtitle for something other than "Bar" vs "Club" (e.g., maybe the address of the bar/club?), and the current model seems to conflate a UI attribute (i.e. what shows up in the callout) with a state property (i.e. a variable that controls which annotation view type to use). Not a big deal, but just an suggestion.
Upvotes: 3