20
votes

I have a UIViewController setup in a storyboard with a tableview and UISearchDisplayController.

I am trying to use a custom prototype cell from self.tableview (which is connected to main tableview in the storyboard). It works fine if self.tableview had returned at least 1 cell when I load my view, but if self.tableview doesn't load a cell (as there is no data), and I load up the UISearchBar and search, the cellForRowAtIndexPath: method crashes:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomSearchCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"CustomSearchCell" forIndexPath:indexPath];

    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}

-(void)configureCell:(CustomSearchCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    User *user = [self.fetchedResultsController objectAtIndexPath:indexPath];

    cell.nameLabel.text = user.username;
}

Errors:

*** Assertion failure in -[UITableViewRowData rectForRow:inSection:heightCanBeGuessed:]
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for rect at invalid index path (<NSIndexPath: 0x9ef3d00> {length = 2, path = 0 - 0})

My fetchedResultsController seems to have data (1 section, 2 rows) at the point the above method is called. It crashes on the dequeueReusableCellWithIdentifier line.

Any pointers/ideas? It should dequeue the prototype cell from self.tableview, but my guess is there was none created in self.tableview so this is the cause?

3
Can you post the code of configureCell:atIndexPath: method? The problem may be in thereLucas Eduardo
it crashes before it gets there... I will add it thoughmootymoots
added above... doesnt really do muchmootymoots
After your dequeueReusableCellWithIdentifier you must check if (cell == nil), and if so, you need to create a cell.ott--
With the prototype cell defined in a storyboard, dequeueReusableCellWithIdentifier should always return a valid cell.Martin R

3 Answers

60
votes

UISearchDisplayController manages it's own UITableView (filtered table), in addition to having your primary table. The cell identifier in the filtered table doesn't match your primary table. You also want to fetch the cell not by indexPath as both tables can be vastly different from each other with respect to number of rows, etc.

So instead of doing this:

UITableViewCell *cell =
[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];

instead do this:

UITableViewCell *cell =
[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
7
votes

I solved this by duplicating the prototype cell into a new xib:

In viewDidLoad:

[self.searchDisplayController.searchResultsTableView registerNib:[UINib nibWithNibName:@"CustomSearchCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CustomSearchCell"];

And updated cellForRowAtIndexPath to use the method's tableview not the original self.tableview:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomSearchCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomSearchCell" forIndexPath:indexPath];

    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}
-1
votes

If you use à UISearchDisplayController in the methode celForRowAtIndexPath, you must use the tableView parameter methode and not the retain pointer of the controller.

try with this code

(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomSearchCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomSearchCell" forIndexPath:indexPath];