Ios 在UITableViewController中使用UISearchDisplayController时断言失败

Ios 在UITableViewController中使用UISearchDisplayController时断言失败,ios,ios6,uitableview,uisearchdisplaycontroller,Ios,Ios6,Uitableview,Uisearchdisplaycontroller,我一直在尝试向我的应用程序中的TableViewController添加简单的搜索功能。我遵循雷·温德里希的指导。我有一个带有一些数据的tableView,我在故事板中添加了搜索栏+显示控制器,然后我有以下代码: #pragma mark - Table View - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

我一直在尝试向我的应用程序中的TableViewController添加简单的搜索功能。我遵循雷·温德里希的指导。我有一个带有一些数据的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:method的全部目的?不管怎样,我迷路了。我错过了什么?请帮忙。提前感谢您花了这么多时间(:


Alex.

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

在不使用“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对单元格进行出列,则当您有分区主列表和普通搜索列表时,可能会导致崩溃。
此代码在任何情况下都能正常工作。

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

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

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

详情如下:

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

这让我感到惊讶,因为在iOS 7上…表视图正在被重用。因此,如果您愿意,可以在
viewDidLoad
中注册该类。出于传统的考虑,我将使用我提到的委托方法保留我的注册。

我也在编写该教程。默认的TableViewController具有“forIndexPath”在他的例子中,它并不存在。一旦我删除了它,搜索就开始了

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

//Replace with
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

搜索后,CellForRowatineXpath方法的“tableView”似乎不是您定义的表的实例。因此,您可以使用定义该单元格的表的实例。而不是:

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


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

当我遇到这个问题时,解决方案是将
tableView
dequeueReusableCellWithIdentifier:@yourcell with
self.tableView

替换为swift 3您只需要添加self:

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

    ...
}

这难道不只是将新单元格从一个表无限期地实例化到另一个表吗?如果将单元格从一个表中出列并交给另一个表听起来像是一个坏主意,我认为这也会起作用。事实并非如此。在我的情况下,尝试将单元格从主表中出列以搜索表有时会导致崩溃。不起作用。尝试搜索,然后取消l(退出覆盖结果模式)然后再次搜索。崩溃。建议的解决方案仍然为我提出了一个例外。但是,如果我将
dequeueReusableCellWithIdentifier:forIndexPath:
替换为
dequeueReusableCellWithIdentifier:
。谢谢!问题是self.tableview而不是tableview!救生衣!如果您的cell在故事板中是自定义的,需要从它而不是它的类中实例化。不幸的是,这不适用于故事板动态原型单元。但它适用于nib注册的单元。解决方法很好。不幸的是,这不适用于故事板动态原型单元。+1.在我的swift实现中需要self.tableView of这一概念。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) as! YourCell

    ...
}