API call with UISearchBar

I have a UITableView that displays API results. The API is called whenever the user enters into the UISearchBar through searchBar: textDidChange :. Effectively perform autocomplete searches. My problem is that the results loaded into the UITableView seem to iterate after the last API call.

Example: Custom types are "combined" in a UISearchBar, but the results are not displayed in the UITableView. The user enters any character after "union", "union", for example, and the API results from "union" are displayed in the UITableView. When the user scrolls the results (from the โ€œunionsโ€, but really โ€œcombinesโ€), the โ€œre-filled cellsโ€ display the result of the โ€œunionsโ€.

SearchViewController.h

#import <UIKit/UIKit.h> @interface SearchViewController : UIViewController <UITextFieldDelegate, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource, UISearchDisplayDelegate>{ UITableView *searchTableView; UISearchBar *sBar; UISearchDisplayController *searchDisplayController; } @property (strong, nonatomic) NSArray *loadedSearches; @end 

SearchViewController.m

 #import "SearchViewController.h" #import "AFJSONRequestOperation.h" @interface SearchViewController () @end @implementation SearchViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = @"Search"; } return self; } - (void)viewDidLoad { [super viewDidLoad]; searchTableView = [[UITableView alloc] initWithFrame:self.view.bounds]; searchTableView.delegate = self; searchTableView.dataSource = self; [self.view addSubview:searchTableView]; sBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 160, 44)]; sBar.placeholder = @"Bus Route to..."; sBar.delegate = self; searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:sBar contentsController:self]; searchDisplayController.delegate = self; searchDisplayController.searchResultsDataSource = searchTableView.dataSource; searchDisplayController.searchResultsDelegate = searchTableView.delegate; searchTableView.tableHeaderView = sBar; } -(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { NSString *searchQuery = [NSString stringWithFormat:@"https://api.foursquare.com/v2/venues/search?ll=40.4263,-86.9177&client_id=xxx&client_secret=yyy&v=20121223&query='%@'",searchText]; searchQuery = [searchQuery stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [[NSURL alloc] initWithString:searchQuery]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){ self.loadedSearches = JSON[@"response"][@"venues"]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){ NSLog(@"%@", error.localizedDescription); }]; [operation start]; [searchTableView reloadData]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.loadedSearches.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if(cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; } cell.textLabel.text = self.loadedSearches[indexPath.row][@"name"]; return cell; } @end 

If my problem is not clear, let me know.

Feel free to criticize other aspects of the code, however I would really appreciate a solution to my problem :) Thanks in advance.

An example API response is http://pastebin.com/UZ1H2Zwy

+4
source share
2 answers

The problem is that you are updating the table before you receive data when you perform an asynchronous operation with AFJSONRequestOperation. So your model is probably updating correctly, but your column is one update. Try moving [searchTableView reloadData] inside the block success callback:

 AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { self.loadedSearches = JSON[@"response"][@"venues"]; // refreshing the TableView when the block gets the response [searchTableView reloadData]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { NSLog(@"%@", error.localizedDescription); }]; 

Hope this works.

+2
source

Your queries work asynchronously, this is not related to scrolling or anything else. Only the result returns at that time. Try canceling previous requests. For example, if you try to find "unions", cancel the query "union". Hope this helps.

0
source

All Articles