2 Stimmen

Batch Geocode MKLocalSearchResponse

Ich habe eine Suchfunktion eingerichtet, die die Antwort einer MKLocalSearchRequest in einem UITableView anzeigt

Ich möchte alle Antworten von der Response jeder Suche bereinigen. Hier ist mein Versuch, dies bisher zu erreichen, inspiriert von diesem Beitrag Multiple Locations on Map (using MKMapItem and CLGeocoder)

Hier ist mein Code.

@interface ViewController () 
@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;

    //Das Problem liegt wahrscheinlich hier. Wie soll ich das MKMapItem im Array verarbeiten?
    //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

Ich bin mir nicht sicher, wie ich jedes MKMapItem verarbeiten soll. Im Moment wirft es diesen Fehler

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

1voto

Rob Punkte 389782

Die CLGeocoder-Methode geocodeAddressString, auf die in der anderen Frage verwiesen wird, ist für das Geokodieren einer Adresse vorgesehen.

Sie führen jedoch eine MKLocalSearch innerhalb einer bestimmten Region durch, die MKMapItem-Objekte zurückgibt, die bereits geokodiert sind. Daher können Sie den geocodeAddressString-Code vollständig aus Ihrem Codebeispiel entfernen.

Tatsächlich erklärt dies die Ursache Ihrer Ausnahme, dass Sie das von MKLocalSearch zurückgegebene MKMapItem nehmen und versuchen, es als Suchzeichenparameter der CLGeocoder-Methode geocodeAddressString zu verwenden (die nur zum Suchen von Zeichenkettenrepräsentationen von Adressen verwendet wird).

Im Grunde genommen ist es viel einfacher, eine lokale Suche durchzuführen und die Ergebnisse in der Karten-App anzuzeigen, als Sie oben erwogen haben. Alles was Sie tun müssen, ist:

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

Oder, wenn Sie es auf Ihrer eigenen MKMapView anzeigen möchten, könnten Sie etwas Ähnliches tun

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

In der Praxis könnten Sie in diesem letzten Beispiel, in dem Sie die Ergebnisse auf Ihrer eigenen Kartenansicht anzeigen, Ihre eigene benutzerdefinierte Annotationsklasse erstellen, damit Sie eine größere Kontrolle über Ihre Darstellung der Annotationsansicht in der Methode viewForAnnotation haben. Aber hoffentlich verdeutlicht dies die Hauptbeobachtung, dass beim Verwenden von MKLocalSearch die CLGeocoder-Methode geocodeAddressString überhaupt nicht verwendet werden sollte.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X