地图上的多个位置(使用MKMapItem和CLGeocoder) [英] Multiple Locations on Map (using MKMapItem and CLGeocoder)

查看:189
本文介绍了地图上的多个位置(使用MKMapItem和CLGeocoder)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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];
    }];
}


推荐答案

您是正确的,您一次只能发送一个地理编码请求。实际上, CLGeocoder类参考说我们的应用应该为任何一个用户操作发送最多一个地理编码请求。

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.

有很多不同的方法来解决这个问题,但是一个特别优雅的方法是使用并发的 NSOperation ,它不会完成操作(即不执行 isFinished KVN),直到地理编码请求的异步完成块被调用。 (有关并发操作的信息,请参阅并发执行操作部分/OperationObjects/OperationObjects.html#//apple_ref/doc/uid/TP40008091-CH101-SW1rel =nofollow> Operation Queue 一章)。然后只需将这些操作添加到串行操作队列。

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 the isFinished 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:

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];

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

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.

这篇关于地图上的多个位置(使用MKMapItem和CLGeocoder)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆