Batch Geocode MKLocalSearchResponse

时间:2014-08-22 03:02:44

标签: ios mapkit mklocalsearch mklocalsearchrequest

我有一个搜索设置,在UITableVIew中显示MKLocalSearchRequest的响应

我想从每次搜索的响应中清除所有响应。这是我到目前为止完成此项目的镜头,受到这篇文章的启发Multiple Locations on Map (using MKMapItem and CLGeocoder)

这是我的代码。

@interface ViewController () <UISearchBarDelegate,UISearchDisplayDelegate,UITextFieldDelegate>
@property (nonatomic, strong) UISearchDisplayController *searchController;
@property (nonatomic, strong) UISearchBar *searchBar;

@property (nonatomic, strong) MKLocalSearch *localSearch;
@property (nonatomic, strong) MKLocalSearchResponse *localSearchResponse;

@property (nonatomic, strong) NSArray *dirtyResponseArray;
@property (nonatomic, strong) NSMutableArray *geocodedResultsArray;
@end

@implementation ViewController

-(void)startSearch:(NSString *)searchString
{
    if (self.localSearch.searching)
        [self.localSearch cancel];

    MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
    request.naturalLanguageQuery = searchString;
    request.region = MKCoordinateRegionMake(self.currentLocation.coordinate, self.mapView.region.span);

    MKLocalSearchCompletionHandler completionHandler = ^(MKLocalSearchResponse *response, NSError *error){

        if (error != nil) return;

        else {
            self.dirtyResponseArray = response.mapItems;                
            [self operation];
            [self.searchController.searchResultsTableView reloadData];
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        }

        [self.searchDisplayController.searchResultsTableView reloadData];
    };

    if (self.localSearch != nil)
        self.localSearch = nil;

    self.localSearch = [[MKLocalSearch alloc] initWithRequest:request];
    [self.localSearch startWithCompletionHandler:completionHandler];
}

-(void)operation
{
    CLGeocoder *geocoder = [[CLGeocoder alloc]init];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    NSOperation *finalCompletionOperation = [NSBlockOperation blockOperationWithBlock:^{
        [MKMapItem openMapsWithItems:self.geocodedResultsArray launchOptions:nil];
        NSLog(@"Local Search Response To use in tableview =================== %@", self.geocodedResultsArray);
    }];

    NSOperation *previousCompletionHandler = nil;

    //Issue is probably right here. How should I handle the MKMapItem in the array?
    //NSString *address = [self.dirtyResponseArray valueForKey:@"address"][@"formattedAddress"]; ??

    for (NSString *address in self.dirtyResponseArray) {

        NSBlockOperation *geocodeRequest = [[NSBlockOperation alloc] init];
        if (previousCompletionHandler) [geocodeRequest addDependency:previousCompletionHandler];
        NSBlockOperation *geocodeCompletionHandler = [[NSBlockOperation alloc] init];
        [finalCompletionOperation addDependency:geocodeCompletionHandler];

        [geocodeRequest addExecutionBlock:^{ [geocoder geocodeAddressString:address 
                        completionHandler:^(NSArray *placemarks, NSError *error) 
        {
                [geocodeCompletionHandler addExecutionBlock:^{
                    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];
                        [self.geocodedResultsArray addObject:mapItem];
                    }
                }];
                [queue addOperation:geocodeCompletionHandler];
            }];
        }];
        [queue addOperation:geocodeRequest];
        previousCompletionHandler = geocodeCompletionHandler;
    }
    [queue addOperation:finalCompletionOperation];
}
@end

我不确定如何处理每个MKMapItem。现在它抛出这个错误

 -[MKMapItem length]: unrecognized selector sent to instance 0x7f813c9c6200

1 个答案:

答案 0 :(得分:1)

在其他问题中引用的CLGeocoder方法geocodeAddressString用于对地址进行地理编码。

但您在特定区域内执行MKLocalSearch,该区域会返回已经过地理编码的MKMapItem个对象。因此,您可以从代码示例中完全删除geocodeAddressString代码。

事实上,这解释了您的例外来源,即您正在使用MKMapItem返回的MKLocalSearch,并尝试将其用作{{1}的搜索字符串参数方法CLGeocoder(仅用于查找地址的字符串表示)。

底线,进行本地搜索并在地图应用中显示结果比上面考虑的要容易得多。您所需要做的就是:

geocodeAddressString

或者,如果您想在自己的MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init]; request.naturalLanguageQuery = searchString; request.region = region; MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request]; [search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) { [MKMapItem openMapsWithItems:response.mapItems launchOptions:nil]; }]; 上展示它,您可以执行类似

的操作
MKMapView

实际上,在后一个您在自己的地图视图中显示结果的示例中,您可以创建自己的自定义注记类,以便更好地控制{{1}中注释视图的呈现} 方法。但希望这说明了一个主要观点,即在使用MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init]; request.naturalLanguageQuery = searchString; request.region = region; MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request]; [search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) { for (MKMapItem *item in response.mapItems) { [self.mapView addAnnotation:item.placemark]; } }]; 时,您根本不应该使用viewForAnnotation方法MKLocalSearch