I'm trying to display multiple locations in MKMapItem
. I am getting those locations from a CLGeocoder
, unfortunately it only accepts one location. Even though I pass in an NSArray
it just returns one location.
The following works fine with a single location, but not with multiple locations. How can I geocode multiple locations?
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) {
NSArray *addresses = @[@"Mumbai",@"Delhi","Banglore"];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:@[addresses] completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *geocodedPlacemark = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:geocodedPlacemark.location.coordinate addressDictionary:geocodedPlacemark.addressDictionary];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:geocodedPlacemark.name];
[MKMapItem openMapsWithItems:@[mapItem] launchOptions:nil];
}];
}
For Guys looking for Swift Solution:
Thanks to Apple. Official doc link
You can use the snippet in the following way for multiple addresses:
In answer to your question, you are correct that you can only send one geocode request at one time. In fact, the CLGeocoder Class Reference says that our apps should "send at most one geocoding request for any one user action."
So, to do this, you must send separate requests. But these requests (which run asynchronously) should not be running concurrently. So, the question is how to make a series of asynchronous geocode requests run sequentially, one after another.
There are lots of different ways of tackling this, but one particularly elegant approach is to use a concurrent
NSOperation
subclass, which doesn't complete the operation (i.e. doesn't perform theisFinished
KVN) until the asynchronous completion block of the geocode request is called. (For information about concurrent operations, see the Configuring Operations for Concurrent Execution section of the Operation Queue chapter of the Concurrency Programming Guide). Then just add those operations to a serial operation queue.Another approach is to make this asynchronous geocode request behave in a synchronous manner, and then you can just add the requests to a serial queue and the requests will be performed sequentially rather than in parallel. You can achieve this through the use of semaphores, effectively instructing the dispatched task to not return until the geocode request complete. You could do it like so:
Alternatively, you could employ more traditional patterns, too. For example, you could write a method that performs a single geocode request, and in the completion block, initiates the next request, and repeat that process until all the requests are made.