I need to show on my MkMapView about 10 locations (and respective annotations) and after pressing a button I need to add new different annotations according to different JSON parsing results (for example a locationIDValue < 100 means a red pin, otherwise green). This is the simplified code:
- (void)viewDidLoad
{
[super viewDidLoad];
map.showsUserLocation = true;
map.mapType = MKMapTypeStandard;
arrayID = [[NSMutableArray alloc] initWithObjects: @"id1", @"id2", @"id3", @"id4", @"id5", @"id6", @"id7", @"id8", @"id9", @"id10", nil];
#define MakeLocation(lat,lon) [[CLLocation alloc] initWithLatitude:lat longitude:lon]
locations= @[ MakeLocation(lat1,lon1), MakeLocation(lat2,lon2), MakeLocation(lat3,lon3), MakeLocation(lat4,lon4), MakeLocation(lat5,lon5), MakeLocation(lat6,lon6), MakeLocation(lat7,lon7), MakeLocation(lat8,lon8), MakeLocation(lat9,lon9), MakeLocation(lat10,lon10) ];
for (int l=0; l<[locations count]; l++) { // HERE ITS PERFECT! I CAN SEE ALL 10 ANNOTATIONS!
MKPointAnnotation* annotation= [MKPointAnnotation new];
annotation.coordinate = [locations[l] coordinate];
[map addAnnotation: annotation];
}
}
and
- (IBAction)parseMethod {
[map removeAnnotations:map.annotations];
for (int i=0; i < [arrayID count]; i++) { // arrayID contains ID values to parse for each location
NSURL *url = [NSURL URLWithString:
[NSString stringWithFormat:
@"http://JSONPARSINGURL/%@",[arrayID objectAtIndex:i]]];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0];
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// PARSING CODE . . .
NSMutableArray *value = [JSON objectForKey:@"value"];
NSMutableDictionary *value0 = [value objectAtIndex:0];
[valueID replaceObjectAtIndex:i withObject:[value0 objectForKey:@"valueID"]];
locationIDValue = [[valueID objectAtIndex:i] intValue]; // locationIDValue contains the values that i must use to put different annotations on the map
NSLog(@"locationIDValue: %d", locationIDValue); // here I control IF app parses all the values of locationIDValue
[table reloadData]; // here I put another control to see all values parsed
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(@"FAILURE");
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // I have used also simple [operation start] but I have same issue!
[queue addOperation:operation];
[queue waitUntilAllOperationsAreFinished];
}
NSLog(@"END PARSING"); // here I control the end of parsing, so now I can add new annotations to MKMapView according to locationIDValue array
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
for (int l=0; l<[locations count]; l++) { // HERE I CAN SEE ONLY A SINGLE LOCATION!
annotation.coordinate = [locations[l] coordinate];
NSLog(@"%f - %f", annotation.coordinate.latitude, annotation.coordinate.longitude); // here I control IF app parses all the values of coordinates
[map addAnnotation: annotation];
}
}
and
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pinView"];
pinView.animatesDrop=YES;
if (annotation != map.userLocation)
{
if ( locationIDValue <= 100) {
pinView.pinColor = MKPinAnnotationColorRed;
return pinView;
}
pinView.pinColor = MKPinAnnotationColorGreen;
return pinView;
}
else
map.userLocation.title = @"My position";
return nil;
}
The situation: When I open app for the first time its all right, I can see ALL the annotations dropping on the map, according with the #define MakeLocation latitude and longitude; but if I press the button and start the parseMethod, I wait a few seconds (according to NSOperationQueue, but I can test it also without queue, with simple [operation start] code), then I can see ONLY ONE SINGLE annotation on the map, always the same, strangely on the FIFTH location, with lat5-lon5 coordinates (otherwise, if I change a few code I can see ALL THE ANNOTATIONS dropping on the SAME location). As u can see I write some NSLog code and add UITableView to control the activity, and this is the result:
END PARSING
coordinates: lat1 - lon1
coordinates: lat2 - lon2
coordinates: lat3 - lon3
coordinates: lat4 - lon4
coordinates: lat5 - lon5 <--- THE STRANGE POSITION
coordinates: lat6 - lon6
coordinates: lat7 - lon7
coordinates: lat8 - lon8
coordinates: lat9 - lon9
coordinates: lat10 - lon10
locationIDValue: 100
locationIDValue: 90
locationIDValue: 50
locationIDValue: 120
locationIDValue: 20
locationIDValue: 40
locationIDValue: 80
locationIDValue: 180
locationIDValue: 140
locationIDValue: 10
Well, it seems PERFECT: app parse all the data (also a UITableView populate rows with ALL the new values parsed), so AFTER the end of parsing operation I think we have EVERY value necessary to populate map with new annotations. Well, what is wrong here? Why after parsing I can only see a single annotation? Or, ALL annotations dropping ON THE SAME LOCATION? Please give me an help!
In parseMethod
, change this:
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
for (int l=0; l<[locations count]; l++) { // HERE I CAN SEE ONLY A SINGLE LOCATION!
annotation.coordinate = [locations[l] coordinate];
NSLog(@"%f - %f", annotation.coordinate.latitude, annotation.coordinate.longitude); // here I control IF app parses all the values of coordinates
[map addAnnotation: annotation];
}
to this:
for (int l=0; l<[locations count]; l++) { // HERE I CAN SEE ONLY A SINGLE LOCATION!
//create a NEW annotation for each location...
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = [locations[l] coordinate];
NSLog(@"%f - %f", annotation.coordinate.latitude, annotation.coordinate.longitude); // here I control IF app parses all the values of coordinates
[map addAnnotation: annotation];
}
Move the MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]
to inside the for-loop so that a new annotation object is created for each location.
The existing code there creates a single annotation object and just keeps modifying its coordinate.
What is also really important to note (because it was very hard to find that error and I sat the whole last night in front of this...) is to check if your object that conforms to MKAnnotation has some master base class that imlements the methods isEqual and / or hash on only the data of the base class and you do not overwrite that in your base class. This was my problem and thus isEqual returned YES for all annotations and THUS it showed always only one annotation on the map. I couldn't find any hint on the internet about this so I will leave at least this comment here for poor people in the same situation.
来源:https://stackoverflow.com/questions/14707080/after-json-parsing-viewforannotation-shows-only-one-single-annotation-on-mkmapv