1

I want to implement a search functionality one of my iOS application. I have implemented UISearchBar delegates.

Now when user starts searching it makes a service API call.

For example user types:

  1. A
  2. Ap
  3. App
  4. Appl
  5. Apple

So total 5 service call is made in very short time. Now i want to cancel all the service call made from 1 to 4 and i want to consider the 5th one as my final result.

I googled for the same and found that i should use NSOperationQueue and cancel the operation when not needed. following is the code i am using for that same.

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (searchText.length > 0) {
        [self filterContentForSearchText:searchText];
    }
}

- (void)filterContentForSearchText:(NSString*)searchText {

    if ([session isInternetAvailable:NO]) {
            if (!downloadQ) downloadQ = [[NSOperationQueue alloc] init];
            if (downloadQ) {
                [downloadQ cancelAllOperations];
                NSLog(@"**********cancelAllOperations**********: %@",downloadQ.name);
            }
            downloadQ.name = searchText;

            NSString *strURL = [NSString stringWithFormat:@"http://192.168.1.192:8080/api/user/find/%@/",searchText];
            NSURL *url = [NSURL URLWithString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
            NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url
                                                                  cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
                                                              timeoutInterval:30];

            [urlRequest setHTTPMethod:@"GET"];
            [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
            [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

            [NSURLConnection sendAsynchronousRequest:urlRequest
                                           queue:downloadQ
                               completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                                   NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                                   NSLog(@"===> %@",result);
                               }];
    }
}

I need help on this query. Can any one provide me some solution how can i achieve or what would be the best way to implement searching function in iOS app.

Edit With NSURLSEssion

I tried with following code and how i get the response is different sequence.

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration:defaultConfigObject
                                                                  delegate:nil
                                                             delegateQueue:[NSOperationQueue mainQueue]];

NSString *strURL = [NSString stringWithFormat:@"%@/user/find/%@/",LIVE_SERVICE_HOST_URL,searchText];
NSURL *dataURL = [NSURL URLWithString:strURL];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:dataURL];
[urlRequest setHTTPMethod:@"GET"];
[urlRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

[[delegateFreeSession dataTaskWithRequest:urlRequest
                        completionHandler:^(NSData *data, NSURLResponse *response,
                                            NSError *error){
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@===> %@",searchText,result);
}] resume];

Response come in different sequence:

1st response for A 2nd response for Appl 3ed response for Ap 4th response for Apple 5th response for App

So what can i do to over come this behaviour?

iCoder86
  • 1,874
  • 6
  • 26
  • 46
  • use NSURLSession so you can cancel a request when you need to do. Take a look at: https://www.raywenderlich.com/110458/nsurlsession-tutorial-getting-started – Duyen-Hoa Sep 20 '16 at 08:18
  • @Hoa: I tried with NSURLSession but i got the response from server in different order. Please review my edited question. Can you suggest me what can i do to solve that issue? – iCoder86 Sep 20 '16 at 08:59
  • Take a look at "Querying for Tracks" session in the link that I've posted. They resolve the same use-case as yours. The key idea is to reuse the same dataTask, each time you change the search text, it cancel the current dataTask (if launched) and re-create new one. – Duyen-Hoa Sep 20 '16 at 09:06

1 Answers1

0

Alternate solution:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if ([searchText length] <= 0) {
        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(filterContentForSearchText) object:self];
        [self performSelector:@selector(filterContentForSearchText) withObject:self afterDelay:0.5];
    }
}

Reference From: Here

Community
  • 1
  • 1
iCoder86
  • 1,874
  • 6
  • 26
  • 46