4

API からの結果を表示する UITableView があります。この API は、ユーザーが searchBar:textDidChange: を介して UISearchBar に入力するたびに呼び出されます。オートコンプリート検索を効果的に実装する。私の問題は、UITableView に読み込まれた結果が、最後の API 呼び出しの背後にある反復のように見えることです。

例: ユーザーが UISearchBar に「union」と入力しましたが、結果が UITableView に表示されません。ユーザーが「union」の後に任意の文字を入力すると、たとえば「unions」と「union」の API 結果が UITableView に表示されます。ユーザーが結果 (「ユニオン」ですが、実際には「ユニオン」) を下にスクロールすると、「再入力されたセル」に「ユニオン」の結果が表示されます。

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

問題が明確でない場合は、お知らせください。

コードの他の側面について自由に批評してください。ただし、私の問題の解決策を本当に感謝しています:) よろしくお願いします。

API レスポンスの例 - http://pastebin.com/UZ1H2Zwy

4

2 に答える 2

2

問題は、AFJSONRequestOperation で非同期操作を行っているため、データを取得する前にテーブルを更新しているようです。したがって、モデルはおそらく正しく更新されていますが、テーブルビューは1回更新されています。[searchTableView reloadData] をブロック成功コールバック内に移動してみてください:

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

これがうまくいくことを願っています。

于 2013-01-28T00:28:36.393 に答える
0

Your requests work asynchronously, it is not probably related with scroll or something. Just result returns at that time. Try to cancel the previous requests. For example if you try to search "unions" then cancel the "union" request. Hope it helps.

于 2013-01-26T13:17:41.850 に答える