I’m working on an application using the MapKit in iOS. I’m having trouble because at some point during my program, the order of one of the arrays switches (the array holding the coordinates), causing names of places to be paired with the wrong coordinates. I have narrowed it down to the following area:
for(CLLocation *loc in locationOutputArray)
{
NSLog(@"Location coordinates: %f,%f",[loc coordinate].latitude,
[loc coordinate].longitude);
}
NSLog(@"***************************************");
for(CLLocation *location in locationOutputArray)
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error)
{
NSLog(@"Location coordinates:%f,%f",[location coordinate].latitude,
[location coordinate].longitude);
if(placemarks && placemarks.count > 0)
{
CLPlacemark *topResult = [placemarks objectAtIndex:0];
//NSLog(@"%@",topResult);
NSString *address = [NSString stringWithFormat:@"%@ %@, %@ %@",
[topResult subThoroughfare],
[topResult thoroughfare],
[topResult locality],
[topResult administrativeArea]];
//NSLog(@"Address: %@", address);
[addressOutputArray addObject:address];
Place *place = [[Place alloc]
initWithName:[namesOutputArray objectAtIndex:([addressOutputArray count]-1)]
andAddress:address
andLatitude:[location coordinate].latitude
andLongitude:[location coordinate].longitude
andStartingCoordinate:startingCoordinate];
//NSLog(@"Distance from starting location: %f",[place distanceFromStartingPoint]);
[finalPlaceArray addObject:place];
[place release];
}`
The log statements for before and after the the code block respectively (separated by asterisks) are:
Location coordinates: 40.116903,-75.120631
Location coordinates: 40.129940,-75.060127
Location coordinates: 40.083996,-75.187704
Location coordinates: 40.069180,-75.126812
Location coordinates: 40.095425,-75.127777
Location coordinates: 40.095019,-75.126752
Location coordinates: 40.117596,-75.185366
Location coordinates: 40.105838,-75.212272
Location coordinates: 40.124327,-75.061865
Location coordinates: 40.010910,-75.127223
Location coordinates: 40.061088,-75.092801
Location coordinates: 40.112011,-75.165353
Location coordinates: 40.017103,-75.174498
Location coordinates: 40.139532,-75.207757
Location coordinates: 40.099432,-75.196213
Location coordinates: 40.116903,-75.120631
Location coordinates: 40.061088,-75.092801
Location coordinates: 40.010910,-75.127223
Location coordinates: 40.124327,-75.061865
Location coordinates: 40.112011,-75.165353
Location coordinates: 40.099432,-75.196213
Location coordinates: 40.139532,-75.207757
Location coordinates: 40.017103,-75.174498
Location coordinates: 40.083996,-75.187704
Location coordinates: 40.069180,-75.126812
Location coordinates: 40.129940,-75.060127
Location coordinates: 40.095019,-75.126752
Location coordinates: 40.117596,-75.185366
Location coordinates: 40.095425,-75.127777
Location coordinates: 40.105838,-75.212272
Any help would be much appreciated.
Short answer: You’re printing the locations in the order that the geocoder requests complete, not the order in which they appear in the array.
Longer answer: You’re making a bunch of calls to the geocoder (one call for each location in your array), and passing in a completion handler. Those calls are asynchronous, which means that you’re not waiting for one to complete before you fire off the next one. When each call completes, you print its location. So, the output you’re getting represents the order in which the calls are completing, not the order in which the locations appear in the original array or the order that you made the calls.
Solution: Don’t rely on asynchronous calls to complete in any particular order. If you need the results to appear in some order, you’ll need a way to sort them. It sounds like you’re keeping place names and locations in separate arrays and trying to keep those arrays ordered the same. That’s always a recipe for bugs; you’d be better off keeping everything in a single array, where each entry in the array contains both place name and location. Using a dictionary for each place may be a convenient way to achieve that.