【问题标题】:Assertion failure when using UISearchDisplayController in UITableViewController在 UITableViewController 中使用 UISearchDisplayController 时断言失败
【发布时间】:2012-12-21 20:13:52
【问题描述】:

我一直在尝试向我的应用程序中的 TableViewController 添加简单的搜索功能。我遵循了 Ray Wenderlich 的教程。我有一个带有一些数据的 tableView,我在情节提要中添加了搜索栏 + 显示控制器,然后我有这个代码:

#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'

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

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

瞧!它起作用了...仅在您第一次搜索时。如果您返回原始结果并再次搜索,应用程序会因相同的错误而崩溃。我想也许添加所有的

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

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

亚历克斯。

【问题讨论】:

    标签: ios ios6 uitableview uisearchdisplaycontroller


    【解决方案1】:

    尝试在 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;
    }
    

    这段代码运行良好

    注意

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

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

    改用这个

    [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    

    【讨论】:

    • 这不是无限期地将新单元格从一个表实例化到另一个表吗?如果从一张表中取出单元格并将它们交给另一张表听起来是个坏主意
    • 我认为这也可以。它没有。在我的情况下,尝试将主表中的单元格从搜索表中出列有时会导致崩溃。
    • 不起作用。尝试搜索,然后取消(退出覆盖结果模式),然后再次搜索。崩溃。
    • 建议的解决方案仍然对我提出了例外。但是,如果我将 dequeueReusableCellWithIdentifier:forIndexPath: 替换为 dequeueReusableCellWithIdentifier:,它似乎可以按预期工作。
    • 谢谢! self.tableview 而不是 tableview 是问题!救命稻草!
    【解决方案2】:

    它在第一次运行时运行良好但在您退出结果表并返回进行另一次搜索时崩溃的原因是,每次进入搜索模式时,搜索显示控制器都会加载一个新的UITableView

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

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

    如下:

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

    这让我大吃一惊,因为在 iOS 7 上……表格视图正在被重用。因此,如果您愿意,可以在viewDidLoad 注册课程。为了遗产,我将在我提到的委托方法中保留我的注册。

    【讨论】:

    • 很遗憾,这不适用于 Storyboard 动态原型单元。
    • 但它适用于 nib 注册的单元格。很好的解决方法。
    【解决方案3】:

    经过搜索,cellForRowAtIndexPath 方法的 'tableView' 似乎不是您定义的 Table 的实例。因此,您可以使用定义单元格的表格实例。而不是:

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

    用途:

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

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

    【讨论】:

    • +1。在我快速实施这个概念时需要 self.tableView。
    【解决方案4】:

    不使用 'indexPath' 将单元格出列,如果您获得一个 nil 元素,则必须手动分配它。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"YourCellId"];
        if (!cell)
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"YourCellId"];
    
        // fill your cell object with useful stuff :)
    
        return cell;
    }
    

    当您有一个分段的主列表和一个普通的搜索列表时,尝试使用 self.tableView 使单元格出列可能会导致崩溃。 此代码适用于任何情况。

    【讨论】:

    • 如果您的单元格在 Storyboard 中是自定义的并且需要从它而不是它的类中实例化,这将不起作用。
    【解决方案5】:

    当我遇到这个问题时,解决方案是将tableViewdequeueReusableCellWithIdentifier:@yourcell 替换为self.tableView

    【讨论】:

      【解决方案6】:

      我也在研究那个教程。默认的 TableViewController 具有“forIndexPath”,在他的示例中它不存在。一旦我删除它,搜索就会起作用。

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

      【讨论】:

      • 很遗憾,这不适用于 Storyboard 动态原型单元。
      【解决方案7】:

      对于 swift 3,您只需要添加 self:

      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
      {
          let cell = self.tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) as! YourCell
      
          ...
      }
      

      【讨论】:

        猜你喜欢
        • 2012-08-01
        • 1970-01-01
        • 2019-02-11
        • 2018-10-11
        • 1970-01-01
        • 2022-10-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多