There are several issues here but to answer your two main questions first:
- To set
leftCalloutAccessoryView
to a different image for each annotation, you need to look at some value in theannotation
parameter that is passed to theviewForAnnotation
delegate method. At the crudest level, you could set the image based on the value ofannotation.title
(eg. if title is "A" then set image to "1" else if title is "B" then set image to "2" etc). Tapping on the
rightCalloutAccessoryView
gives you the wrong Event Id because of this code indidSelectAnnotationView
:_eventIndex = [_mapView.annotations indexOfObject:view.annotation];
The above code assumes that the
annotations
array that the map view returns will be in the same exact order that you added the annotations in (and that it will only contain annotations that you added which isn't the case ifshowsUserLocation
isYES
). This assumption is false. Do not assume theannotations
array is in any particular order -- do not rely on its order.A better solution is to use the annotation object itself that you can access directly from the
calloutAccessoryControlTapped
delegate method usingview.annotation
.Since you need the Event's Id and the default
MKPointAnnotation
class obviously has no property to store that anywhere, you should create your own class (eg.EventAnnotation
) that implementsMKAnnotation
and add all the event properties you need to know for each annotation. Then, you'll be able to access event-specific values directly using theannotation
object in the map view's delegate methods without trying to reference back to your original arrays.The
EventAnnotation
class might be declared like this:@interface EventAnnotation : NSObject<MKAnnotation> @property (assign) CLLocationCoordinate2D coordinate; @property (copy) NSString *title; @property (copy) NSString *subtitle; @property (copy) NSString *eventId; //Not sure if your event id is a string. //Change to "@property (assign) int eventId;" if it's an integer. @end
Then to create the annotation, create an
EventAnnotation
instead ofMKPointAnnotation
:EventAnnotation *aAnnotationPoint = [[EventAnnotation alloc] init]; CLLocationCoordinate2D theCoordinate; theCoordinate.latitude = [_arrEventLatitude[i] doubleValue]; theCoordinate.longitude = [_arrEventLongitude[i] doubleValue]; aAnnotationPoint.coordinate = theCoordinate; aAnnotationPoint.title = _arrEventNames[i]; aAnnotationPoint.subtitle = _arrEventDescription[i]; //store event id in the annotation itself... aAnnotationPoint.eventId = _arrID[i]; [_mapView addAnnotation:aAnnotationPoint];
Finally, in
calloutAccessoryControlTapped
(you won't need to implementdidSelectAnnotationView
), you could do this:EventViewerViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"EventViewer"]; [self.navigationController pushViewController:controller animated:YES]; //cast the view's annotation object to EventAnnotation... EventAnnotation *eventAnn = (EventAnnotation *)view.annotation; NSDictionary *selection = @{@"ID" : eventAnn.eventId, @"eventName" : eventAnn.title }; [controller setValue:selection forKey:@"selection"];
Another thing you should do in viewForAnnotation
is explicitly set the view's annotation
property immediately after creating it. Although it may be getting assigned automatically somehow, I'd rather do it explicitly to be safe:
EventAnnotationView *viewAnno = [[EventAnnotationView alloc] initWithFrame:myRect];
viewAnno.annotation = annotation; // <-- add this
Two unrelated points:
- Instead of creating a separate array for each event property (Ids, Names, Descriptions, Latitudes, etc), I would highly recommend creating an "Event" class with all those properties and then you could create just one array of Event objects. In fact, you could make this Event class implement MKAnnotation itself (instead of creating two classes Event and EventAnnotation).
- The code is executing a separate SQL query for each column. All the queries are identical except for the column retrieved. This could be improved greatly by getting all the columns in a single SQL query (eg.
SELECT ID, Name, Latitude, Longitude, Description FROM Event ORDER BY DateTime DESC
). I am not familiar with thisDBGMScr
class but you should really look into it. If the table contains 500 annotations and 5 columns, you are currently retrieving a total of 2500 rows when it could be just 500 in one shot.