0

I want to get an array of nearby locations using mapkit framework. So when the user types in a textfield I call the following function.

- (void)searchForLocations:(NSString *)string
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(search:) object:nil];
    [self performSelectorInBackground:@selector(search:) withObject:string];
}

- (void)search :(NSString *)string
{
    MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
    request.naturalLanguageQuery = string;
    MKCoordinateRegion region;
    MKCoordinateSpan span;
    span.latitudeDelta = 0.05;
    span.longitudeDelta = 0.05;

    region.span = span;
    region.center = newLocation.coordinate;

    request.region = region;

    MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];

    [search startWithCompletionHandler:^(MKLocalSearchResponse
                                         *response, NSError *error) {
        if (response.mapItems.count == 0)
        {
            NSLog(@"No Matches");
        }
        else
        {

            NSLog(@"name = %@", item.name);
            NSLog(@"Phone = %@", item.phoneNumber);
        }
    }];
}

As you can see I want to cancel the previous search if a new input text is coming. But the previous search is not cancelled. How can i cancel the previous search?

Thanks in advance.

Jasper
  • 7,031
  • 3
  • 35
  • 43
jjpp
  • 1,298
  • 1
  • 15
  • 31

3 Answers3

2

There is a cancel method on MKLocalSearch. Have you tried that one?

Edit: Ah, sorry, I was being stupid. You need to keep a reference to your old search in some way in order to cancel it. Put it in a property which you can clear (i.e. set to nil) when the search is finished. Whenever you call the search function, cancel the previous search function (no "if" needed, nil swallows all), then create a new one

@property (nonatiomic, strong) MKLocalSearch *previousSearch;

- (void)search :(NSString *)string
{
    [self.previousSearch cancel];
    MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
    request.naturalLanguageQuery = string;
    MKCoordinateRegion region;
    MKCoordinateSpan span;
    span.latitudeDelta = 0.05;
    span.longitudeDelta = 0.05;

    region.span = span;
    region.center = newLocation.coordinate;

    request.region = region;

    MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];

    [search startWithCompletionHandler:^(MKLocalSearchResponse
                                     *response, NSError *error) {
        self.previousSearch = nil;
        if (response.mapItems.count == 0)
        {
            NSLog(@"No Matches");
        }
        else
        {

            NSLog(@"name = %@", item.name);
            NSLog(@"Phone = %@", item.phoneNumber);
        }
    }];

    self.previousSearch = search;
}
Yaser
  • 408
  • 2
  • 6
0

The MKLocalSearch object has a cancel method that you can use to cancel a pending search. You can't simply cancel the selector as you are trying to do as that selector will complete very quickly, with the MKLocalSearch dispatched in the background.

You will need a property to store your search object, so that you can tell if it is still searching and cancel the search if required.

@property (strong,nonatomic) MKLocalSearch *localSearch;

- (void)search :(NSString *)string
{
    MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
    request.naturalLanguageQuery = string;
    MKCoordinateRegion region;
    MKCoordinateSpan span;
    span.latitudeDelta = 0.05;
    span.longitudeDelta = 0.05;

    region.span = span;
    region.center = newLocation.coordinate;

    request.region = region;

    if (self.localSearch!=nil) {
        if (self.localSearch.searching) {
            [self.localSearch cancel];
            self.localSearch=nil;
        }
    }

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

    [search startWithCompletionHandler:^(MKLocalSearchResponse
                                         *response, NSError *error) {
        if (response.mapItems.count == 0)
        {
            NSLog(@"No Matches");
        }
        else
        {

            NSLog(@"name = %@", item.name);
            NSLog(@"Phone = %@", item.phoneNumber);
        }
    }];
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
-1

Well you can use NSBlockOperation. Suppose the global variable that you have used for NSBlockOperation is blockOperation. Then :

[search startWithCompletionHandler:^(MKLocalSearchResponse
                                     *response, NSError *error) {
    blockOperation = NSBlockOperation(block: { () -> Void in
         if (response.mapItems.count == 0) {
            NSLog(@"No Matches");
         } else {
            NSLog(@"name = %@", item.name);
            NSLog(@"Phone = %@", item.phoneNumber);
         }
    })
}];

Then you can use this blockOperation to cancel wherever you want as follows:

blockOperation.cancel()
Jaycee
  • 159
  • 6