Пакетный геокод MKLocalSearchResponse
У меня есть настройка поиска, которая отображает ответ MKLocalSearchRequest в UITableVIew
Я хочу очистить все ответы от ответа каждого поиска. Вот мой пример достижения этой цели, вдохновленный этим постом " Несколько местоположений на карте" (с использованием MKMapItem и 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 ответ
CLGeocoder
метод, geocodeAddressString
, который упоминается в этом другом вопросе, предназначен для геокодирования адреса.
Но вы выполняете MKLocalSearch
в определенном регионе, который возвращает MKMapItem
объекты, которые уже геокодированы. В результате вы можете полностью удалить geocodeAddressString
код из вашего примера кода.
На самом деле, это объясняет источник вашего исключения, что вы принимаете MKMapItem
вернулся MKLocalSearch
и пытается использовать его в качестве параметра строки поиска 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
Вы могли бы сделать что-то вроде
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
совсем.