在UITableViewController中使用UISearchDisplayController时声明失败

我一直在尝试添加简单的searchfunction到我的应用程序中的TableViewController。 我跟随了Ray Wenderlich的教程。 我有一个tableView与一些数据,我添加了故事板中的search栏+显示控制器,然后我有这样的代码:

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

标准的东西,但是当我在search栏中input文本时,每次都会出现这个错误:

 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中,单元格的处理和出队系统发生了变化,并且search使用了不同的tableView,所以我认为问题在于searchtableView和过滤结果不知道单元格,所以我把这在我的viewDidLoad:

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

瞧! 它的工作…只有你第一次search。 如果你回到原来的结果并再次search,该应用程序崩溃与相同的错误。 我想也许加上所有的

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

东西的cellForRow方法,但是这不符合具有dequeueReusableCellWithIdentifier:forIndexPath:方法的整个目的? 无论如何,我迷路了。 我错过了什么? 请帮助。 所有的时间提前谢谢你(:

亚历克斯。

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

之所以在第一次运行时效果很好,但是如果退出结果表并返回进行其他search,则会崩溃,因为每次进入search模式时,search显示控制器都会加载一个新的UITableView

通过search模式我的意思是,你已经点击了文本框,你已经开始键入,在这一点上生成一个表视图来显示结果,退出这个模式,通过点击取消button。 当您第二次点击文本字段并再次input时 – 这是第二次进入“search模式”。

因此,为了避免崩溃,您应该registry视图的单元类,以在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注册这个类。 对于遗留的问题,我将使用我提到的委托方法保留我的注册。

search后,cellForRowAtIndexPath方法的'tableView'似乎不是您定义的表的一个实例。 所以,你可以使用定义单元格的表格的一个实例。 代替:

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

使用:

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

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

在不使用'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来出列单元格可能会导致崩溃,当您有一个分区的主列表和普通的search列表。 这个代码可以在任何情况下工作。

当我有这个问题,解决scheme是取代tableView dequeueReusableCellWithIdentifier:@yourcell与self.tableView

我正在研究这个教程。 默认的TableViewController有“forIndexPath”,在他的例子中它不存在。 一旦我删除它的search工作。

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

对于swift 3,你只需要添加自己:

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