1. ホーム
  2. ios

[解決済み] UITableViewControllerでUISearchDisplayControllerを使用する際のアサーション失敗について

2023-07-10 05:35:07

質問

私のアプリのTableViewControllerに簡単な検索機能を追加しようとしています。Ray Wenderlichのチュートリアルに従いました。私はいくつかのデータを持つtableViewを持っており、私はstoryboardで検索バー+ディスプレイコントローラを追加し、そして私はこのコードを持っています。

#pragma mark - Table View
     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BreedCell" forIndexPath:indexPath];

        //Create PetBreed Object and return corresponding breed from corresponding array
        PetBreed *petBreed = nil;

        if(tableView == self.searchDisplayController.searchResultsTableView)
            petBreed = [_filteredBreedsArray objectAtIndex:indexPath.row];
        else
            petBreed = [_breedsArray objectAtIndex:indexPath.row];

        cell.accessoryType  = UITableViewCellAccessoryDisclosureIndicator;
        cell.textLabel.text = petBreed.name;

        return cell;
    }

#pragma mark - Search
    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
        [_filteredBreedsArray removeAllObjects];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchString];
        _filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy];

        return YES;
    }

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
        // Tells the table data source to reload when scope bar selection changes

        [_filteredBreedsArray removeAllObjects];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",self.searchDisplayController.searchBar.text];
        _filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy];
        return YES;
    }

標準的なものですが、検索バーにテキストを入力すると、このエラーで毎回クラッシュしてしまいます。

2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Assertion failure in -[UISearchResultsTableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460
2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier BreedCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

iOS6でセルの処理とデキューの仕組みが変わったこと、また検索では別のtableViewを使うことは理解していたので、フィルタリングされた結果を表示する検索のtableViewがセルについて知らないことが問題だと思い、viewDidLoadにこのように記述しています。

[self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"BreedCell"];

で、出来上がり。うまくいきました... 最初に検索したときだけです。元の結果に戻ってもう一度検索すると、同じエラーでアプリがクラッシュしてしまいます。もしかしたら、すべての

if(!cell){//init cell here};

のようなものをcellForRowメソッドに追加していますが、これはdequeueReusableCellWithIdentifier:forIndexPath:メソッドを持つ全体の目的に反しないでしょうか?とにかく、私は迷っています。何が足りないのでしょうか?助けてください。いつもありがとうございます(。

アレックスです。

どのように解決するのですか?

dequeueReusableCellWithIdentifierでtableViewの代わりにself.tableViewを使用してみてください。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"BreedCell"];

    //Create PetBreed Object and return corresponding breed from corresponding array
    PetBreed *petBreed = nil;

    if(tableView == self.searchDisplayController.searchResultsTableView)
        petBreed = [_filteredBreedsArray objectAtIndex:indexPath.row];
    else
        petBreed = [_breedsArray objectAtIndex:indexPath.row];

    cell.accessoryType  = UITableViewCellAccessoryDisclosureIndicator;
    cell.textLabel.text = petBreed.name;

    return cell;
}

このコードはかなりうまく動作します

注意

高さをカスタマイズしたセルを使用している場合は

[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

代わりにこれを使う

[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];