地图上的多个位置(使用MKMapItem和CLGeocoder)

Gre*_*ode 6 cocoa-touch ios clgeocoder mkmapitem

我正试图在中显示多个位置MKMapItem.我从a获得这些位置CLGeocoder,不幸的是它只接受一个位置.即使我传入NSArray它只是返回一个位置.

以下适用于单个位置,但不适用于多个位置.如何对多个位置进行地理编码?

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];
    }];
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 13

在回答您的问题时,您是正确的,您一次只能发送一个地理编码请求.事实上,CLGeocoder Class Reference表示我们的应用程序应"为任何一个用户操作发送最多一个地理编码请求".

因此,要执行此操作,您必须发送单独的请求.但是这些请求(异步运行)不应该同时运行.因此,问题是如何使一系列异步地理编码请求一个接一个地顺序运行.

有许多不同的解决方法,但一种特别优雅的方法是使用并发NSOperation子类,它不会完成操作(即不执行 isFinishedKVN),直到调用地理编码请求的异步完成块.(有关并发操作的信息,请参阅" 并发编程指南"的" 操作队列"一章中的" 配置并发执行操作"部分).然后只需将这些操作添加到串行操作队列中.

另一种方法是使此异步地理编码请求以同步方式运行,然后您可以将请求添加到串行队列,并且请求将按顺序执行而不是并行执行.您可以通过使用信号量来实现此目的,有效地指示调度任务在地理编码请求完成之前不返回.你可以这样做:

CLGeocoder *geocoder = [[CLGeocoder alloc]init];
NSMutableArray *mapItems = [NSMutableArray array];

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;   // make it a serial queue

NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    [MKMapItem openMapsWithItems:mapItems launchOptions:nil];
}];

NSArray *addresses = @[@"Mumbai, India", @"Delhi, India", @"Bangalore, India"];

for (NSString *address in addresses) {
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

        [geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
            if (error) {
                NSLog(@"%@", error);
            } else if ([placemarks count] > 0) {
                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];

                [mapItems addObject:mapItem];
            }
            dispatch_semaphore_signal(semaphore);
        }];

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    }];

    [completionOperation addDependency:operation];
    [queue addOperation:operation];
}

[[NSOperationQueue mainQueue] addOperation:completionOperation];
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用更传统的模式.例如,您可以编写一个执行单个地理编码请求的方法,并在完成块中启动下一个请求,并重复该过程直到完成所有请求.