在UITableViewController中使用UISearchDisplayController时断言失败

aci*_*708 80 uitableview uisearchdisplaycontroller ios ios6

我一直在尝试将简单的搜索功能添加到我的应用程序中的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;
    }
Run Code Online (Sandbox Code Playgroud)

标准的东西,但是当我在搜索栏中输入文本时,每次都会出现此错误:

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'
Run Code Online (Sandbox Code Playgroud)

据我所知,在iOS 6中,单元格的处理和出列系统发生了变化,而且搜索使用了不同的tableView,所以我认为问题是带有过滤结果的搜索tableView不知道单元格,所以我把这在我的viewDidLoad中:

[self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"BreedCell"];
Run Code Online (Sandbox Code Playgroud)

瞧!它工作...只有你第一次搜索.如果您返回原始结果并再次搜索,则应用程序崩溃时会出现相同的错误.我想也许可以添加所有

if(!cell){//init cell here};
Run Code Online (Sandbox Code Playgroud)

填充到cellForRow方法,但是这不符合dequeueReusableCellWithIdentifier:forIndexPath:方法的全部目的吗?无论如何,我迷路了.我错过了什么?请帮忙.提前感谢您的所有时间(:

亚历克斯.

Fun*_*Kat 193

尝试在dequeueReusableCellWithIdentifier中使用self.tableView而不是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;
}
Run Code Online (Sandbox Code Playgroud)

这段代码效果很好

注意

如果您有自定义高度单元格,请不要使用

[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Run Code Online (Sandbox Code Playgroud)

请改用它

[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Run Code Online (Sandbox Code Playgroud)

  • 建议的解决方案仍然为我提出了一个例外.但是,如果我用`dequeueReusableCellWithIdentifier:`替换`dequeueReusableCellWithIdentifier:forIndexPath:`,它似乎按预期工作. (8认同)
  • 不会只是无限期地将一个表中的新单元格实例化到另一个表格中吗?如果将一个表中的单元格从一个表格中取出并将它们发送给另一个表格,那就好 (4认同)
  • 谢谢!self.tableview而不是tableview是问题!生命保护! (3认同)

Dan*_*iel 14

它首次运行时效果很好,但如果退出结果表然后又进行另一次搜索则崩溃的原因是因为搜索显示控制器UITableView每次进入搜索模式时都会加载新的.

通过搜索模式,我的意思是,您已经点击了文本字段并且您已经开始输入,此时会生成一个表格视图以显示结果,通过点击取消按钮退出此模式.当您第二次点击文本字段并再次开始输入时 - 这是第二次进入"搜索模式".

因此,为了避免崩溃,您应该为表视图注册单元类,以便在searchDisplayController:didLoadSearchResultsTableView:委托方法(from UISearchDisplayDelegate)中而不是在控制器viewDidLoad方法中使用.

如下:

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

这让我感到惊讶,因为在iOS 7上......表视图正在被重用.因此,viewDidLoad如果您愿意,可以注册课程.对于遗产,我会在我提到的委托方法中保留我的注册.

  • 不幸的是,这不适用于Storyboard动态原型单元. (2认同)

小智 12

搜索后,cellForRowAtIndexPath方法的'tableView'似乎不是您定义的Table的实例.因此,您可以使用定义单元格的表的实例.代替:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
Run Code Online (Sandbox Code Playgroud)

使用:

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
Run Code Online (Sandbox Code Playgroud)

(不要使用cellForRowAtIndexPath方法的tableView,请使用self.tableView.)

  • +1.需要self.tableView在我的快速实现这个概念. (2认同)