У меня есть настройка поиска, которая отображает ответ 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
.
Похожие вопросы
Связанные вопросы
Новые вопросы
ios
iOS - мобильная операционная система, работающая на Apple iPhone, iPod touch и iPad. Используйте этот тег [ios] для вопросов, связанных с программированием на платформе iOS. Используйте связанные теги [target-c] и [swift] для проблем, характерных для этих языков программирования.