80

I've been trying to add simple Search functionality to a TableViewController in my app. I followed Ray Wenderlich's tutorial. I have a tableView with some data, I added the search bar + display controller in storyboard, and then I have this code:

#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;
    }

The standard stuff, but when I enter text in the search bar it crashes every time with this error:

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'

I understand that in iOS 6 the handling and dequeueing system for cells changed, and also that the search uses a different tableView, so I thought the problem was that the search tableView with the filtered results didn't know about the cell, so I put this in my viewDidLoad:

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

And voila! It worked... Only the first time you search. If you go back to the original results and search again, the app crashes with the same error. I thought about maybe adding all the

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

stuff to the cellForRow method, but doesn't that go against the whole purpose of having the dequeueReusableCellWithIdentifier:forIndexPath: method? Anyway, I'm lost. What am I missing? Help, please. Thank you in advance for all your time (:

Alex.

4

7 に答える 7

194

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];
于 2013-01-08T18:50:38.960 に答える
14

最初の実行ではうまく機能したが、結果テーブルを終了して別の検索に戻るとクラッシュした理由は、UITableView検索モードに入るたびに検索表示コントローラーが新しいものをロードしているためです。

検索モードとは、テキストフィールドをタップして入力を開始した時点で、結果を表示するテーブルビューが生成され、キャンセルボタンを押すことでこのモードを終了することを意味します。テキストフィールドを 2 回タップして再度入力を開始すると、2 回目の「検索モード」に入ります。

したがって、クラッシュを回避するには、コントローラー メソッドではなくsearchDisplayController:didLoadSearchResultsTableView:デリゲート メソッド (から) で使用するテーブル ビューのセル クラスを登録する必要があります。UISearchDisplayDelegateviewDidLoad

次のように:

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
    [tableView registerClass:[DPContentTableCell class] forCellReuseIdentifier:cellIdentifier];
    [tableView registerClass:[DPEmptyContentTableCell class] forCellReuseIdentifier:emptyCellIdentifier];
}

iOS 7 では ... テーブル ビューが再利用されているため、これには驚きました。そのため、必要に応じてクラスを登録できviewDidLoadます。レガシーのために、前述のデリゲート メソッドで登録を保持します。

于 2013-08-14T09:48:25.567 に答える
12

検索した結果、cellForRowAtIndexPath メソッドの「tableView」は、定義したテーブルのインスタンスではないようです。したがって、セルを定義するテーブルのインスタンスを使用できます。それ以外の:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

使用する:

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

( cellForRowAtIndexPath メソッドのtableViewは使用せず、 self.tableViewを使用してください。)

于 2014-07-12T18:30:24.890 に答える
3

この問題が発生したとき、解決策はtableViewdequeueReusableCellWithIdentifier:@yourcell を置き換えていましたself.tableView

于 2014-10-02T20:23:50.283 に答える
2

私はそのチュートリアルにも取り組んでいます。デフォルトの TableViewController には「forIndexPath」があり、彼の例では存在しません。削除すると、検索が機能します。

//Default code
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

//Replace with
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
于 2013-09-10T15:49:35.153 に答える