批次地址解析MKLocalSearchResponse [英] Batch Geocode MKLocalSearchResponse

查看:91
本文介绍了批次地址解析MKLocalSearchResponse的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a search setup that displays the response of a MKLocalSearchRequest in UITableVIew

我想从每次搜索的响应中清除 all 个响应.到目前为止,这是我为实现这一目标而付出的努力,受到这篇文章的启发

I want to clean up all the responses from the response of each search. Here is my shot at accomplishing this so far, inspired by this post 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.现在它抛出这个错误

I'm not sure how to handle each MKMapItem. Right now its throwing this error

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

推荐答案

在另一个问题中引用的CLGeocoder方法geocodeAddressString旨在对地址进行地理编码.

The CLGeocoder method, geocodeAddressString, which is referenced in that other question, is designed for geocoding an address.

但是您要在特定区域内执行MKLocalSearch,这将返回已进行地理编码的MKMapItem对象.结果,您可以从代码示例中完全删除geocodeAddressString代码.

But you're performing a MKLocalSearch within a particular region, which returns MKMapItem objects which are already geocoded. As a result, you can entirely remove the geocodeAddressString code from your code sample.

实际上,这解释了您的异常的来源,即您采用了MKLocalSearch返回的MKMapItem,并试图将其用作CLGeocoder方法geocodeAddressString的搜索字符串参数(仅用于查找地址的字符串表示形式.

In fact, this explains the source of your exception, that you're taking the MKMapItem returned by MKLocalSearch, and trying to use it as the search string parameter of CLGeocoder method geocodeAddressString (which is only used for looking up string representations of addresses).

最重要的是,进行本地搜索并在地图"应用中显示结果要比上面设想的要容易得多.您需要做的只是:

Bottom line, to do a local search and show the results in the Maps app is far easier than what you've contemplated above. All you need to do is:

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上,则可以执行类似的操作

Or, if you wanted to show it on your own MKMapView, you could do something like

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时,您根本不应该使用CLGeocoder方法geocodeAddressString.

In practice, in this latter example where you're showing results on your own map view, you might create your own custom annotation class so that you have greater control over your rendering of the annotation view in viewForAnnotation method. But hopefully this illustrates the main observation, that when using MKLocalSearch, you should not be using CLGeocoder method geocodeAddressString at all.

这篇关于批次地址解析MKLocalSearchResponse的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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