ios 5 UISearchDisplayController crash
Asked Answered
W

4

24

I am implementing a UITableView with UISearchDisplayController in xcode 4.2. UITableView & UISearchDisplayController are created in StoryBoard. I set the Cell Identifier (SampleCell) for UITableView and access it like

cell = [tableView dequeueReusableCellWithIdentifier:@"SampleCell"];

UItableView is working fine. But once i try to search, the app crash with below error.

*** Assertion failure in -[UISearchResultsTableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:6072
2011-11-09 22:22:16.058 SampleApp[14362:fb03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

I guess I need to set the cell identifier for self.searchDisplayController.searchResultsTableView cell. But I don't know how. Thanks in advance for any help. =)

Whalebone answered 9/11, 2011 at 14:45 Comment(1)
+1 for you saved my time for typing a question.I faced exact sam problem.Senhorita
H
83

Use [self.tableView dequeue...], not [tableView dequeue...].

The cell you're trying to dequeue is linked to your primary view controller's tableView in the storyboard, NOT the searchDisplayController's newly created tableView (which has no cell identifiers linked to it). If you just message "tableView" then your dequeue message goes to the searchDisplayController's tableView since that's what was passed into the cellForRowAtIndexPath:... method.

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

    // do your thing

    return cell;
}
Harvey answered 16/3, 2012 at 15:0 Comment(3)
The new issue is that the search result is loaded into a popover that is not desired. can I somehow use my own (self.tableView) to display search results?Senhorita
This is a very bad approach, as you are depending on another tableView instance. Replies by Cedrick and thejaz are much cleaner and definitely the way to go.Alecto
I'm experiencing issues when the search table view shares the reused cells with the original table view. UIKit (iOS 7.1) may log warning messages "no index path for table cell being reused". Later, it may crash do to accessing invalid indexPaths. Having the search table view use its own cells cache as suggested by others will fix this issue, however may require to manually setup segues and other stuff associated to the cells from the original table view.Acadia
M
16

Hard bug to track indeed, it seems that every time you do a search a new tableview is created. Meaning that your cell registering has to be taken out of ViewDidLoad since this will only work for the first search. Instead use the following delegate method to do cell registering and customization:

    - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
    [self.searchDisplayController.searchResultsTableView 
     registerNib:[UINib nibWithNibName:@"YOURCELLNIB" bundle:nil] forCellReuseIdentifier:@"YOURCELLID"];
    self.searchDisplayController.searchResultsTableView.separatorColor = [UIColor clearColor];
}
Meldameldoh answered 28/11, 2011 at 11:38 Comment(5)
+1. I was dealing with a very similar problem and found that once I removed all calls to registerNib and replaced them with a different method of loading cells everything worked fine.Ommatidium
Do you know how to handle t his ios5 with stoaryboards? I created my own cell that extends UITableView and selected the Custom style in the storyboard. Everything works fine but when filtering the tablview the cell in cellforrowatindexpath is always nil so I get the error : In addition to the erro above I see *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath. How do I create that Custom cell I created in my storyboard programmatically?Whitehead
Thank you, thank you, thank you!!! This was driving me crazy, since I had to necessarily register a nib for the searchResultsTableView cells, and putting the code in viewDidLoad was clearly wrong. If I could upvote your answer again I would do it!Derickderide
THank you. I was just looking for a way to implement this solution but did not know which method searchdisplaycontroller calls when it is created.Noctambulism
Been scratching my head trying to debug this issue for a week. OMG THANKS.Biolysis
L
10

(The answer that recommends using self.tableview is dependent on another table view. This is the cleanest solution and can be used even if the search controller is used by itself.)

You need to register the cells on the UISearchDisplayController's UITableView. The best way to do that is to register the cells when that table view is loaded.

UISearchDisplayDelegate has a method that notifies you when the table view is loaded - just like viewDidLoad but for the search table view.

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
    [tableView registerNib:[UINib nibWithNibName:@"MyCellNib" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MyCellIdentifier"];
}
Louisalouisburg answered 27/3, 2013 at 11:1 Comment(2)
This is by far the best solution to avoid the crash after the first load! I mean, if you just would filter out the already fetched data, the other way would work as expected. But if one should be able to do remote searches, the searchcontroller table view, should clearly not be dependent on the original table view.Akins
Very helpful. See also: registerClass: forCellReuseIdentifier: if your cells are defined in code rather than Interface Builder.Gigigigli
F
0

You can in

- (void)searchDisplayController:(UISearchDisplayController *)searchDisplayController didLoadSearchResultsTableView:(UITableView *)searchResultsTableView

do

[searchResultsTableView registerNib:[UINib nibWithNibName:@"someNibName" bundle:nil] forCellReuseIdentifier:@"yourReuseId"];

Then you're able to use in

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

the normal

[tableView dequeueReusableCellWithIdentifier:

Fries answered 27/9, 2013 at 13:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.