How to work with two different custom cells in one tableView ? Using Storyboard, iOS 7
Solution 1
Beside you are returning nil
for one of your cells, you also has an issue in numberOfRowsInSection
, you are returning 0 rows for section 1!!, although you are expecting rows in this section in your cellForRowAtIndexPath
.
Solution 2
I have made a test and it works fine. These are the steps:
- Create UITableViewController in storyBoard
- Drag and drop UITableViewCell on a UITableViewController below the cell that is already there
- Assign CellIdentifier to both cells (I used Cell1 and Cell2)
- Create 2 subclasses of UITableViewCell (I called them Cell1 and Cell2)
- Create subclass of UITableViewController and name it somehow
-
in cellForRowAtIndexPath method:
static NSString *CellIdentifier = @"Cell1"; static NSString *CellIdentifier1 = @"Cell2"; switch (indexPath.section) { case 0: { Cell1 *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; return cell; } break; case 1: { Cell2 *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1 forIndexPath:indexPath]; return cell; } break; default: break;
}
return nil;
As you can see the implementation is the same as yours
The only way I could reproduce your error is by returning nil in switch block and the documentation for dequeueReusableCellWithIdentifier says:
This method always returns a valid cell.
Even if you messed up your cell identifiers, you still wouldn't get the error you posted. So my conclusion is:
reboot, clean project, restart simulator or something like that cause your scenario according to documentation is not possible...
Related videos on Youtube
Comments
-
JuanM. almost 2 years
I have two custom cells. And I want to display 2 sections in my
UITableView
. The first section with one row displaying the first custom cell, and the second section displaying a list of objects pulled from core data.How should I implement the "cellForRowAtIndexpath" method ?
Here is some of my code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. if (section == 0) { return 1; } else if (section == 1) { //gastos is an array return [self.gastos count]; } return 0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.section) { case 0: { SaldoCelda *cell1 = [tableView dequeueReusableCellWithIdentifier:@"Cell1" forIndexPath:indexPath]; return cell1; } case 1: { static NSString *CellIdentifier = @"Cell"; CeldaGasto *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; NSManagedObject *gasto = [self.gastos objectAtIndex:indexPath.row]; [cell.monto setText:[NSString stringWithFormat:@"%@ AR$", [gasto valueForKey:@"monto"]]]; [cell.categoria setText:[NSString stringWithFormat:@"%@", [gasto valueForKey:@"categoria"]]]; [cell.fecha setText:[NSString stringWithFormat:@"%@", [gasto valueForKey:@"fecha"]]]; return cell; } default: break; } return 0; }
And this is the error message I get:
Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2903.23/UITableView.m:6246 2014-03-05 01:02:57.181 Spendings[2897:70b] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
Thankyou for your help!
-
rmaddy about 10 yearsRead the error. You are returning
nil
for yourcellForRowAtIndexPath:
method. It's either case 0 or case 1. Use the debugger and see which one is the problem. -
rmaddy about 10 yearsBTW - a little side note - there is no need for the
break
statements in yourswitch
for the cases that end inreturn
. Thebreak
statements will never be reached in those cases.
-
-
rmaddy about 10 yearsWhile the implementation of
numberOfRowsInSection:
is incorrect as you point out, that really has nothing to do with the crash. But it does narrow down the problem incellForRowAtIndexPath:
to thecase 0:
code. -
Tarek Hallak about 10 yearshmmm, agree 100% ;) but still yet another issue he should take care of it.
-
JuanM. about 10 yearsOK, I just fix that, but my problem still goes. The section 0 is only having one row as I want, and the section 1 has the count of "gastos".
-
rmaddy about 10 yearsBut you haven't fixed the fact that you return
nil
incase 0
of yourcellForRowAtIndexPath
method. The call to[tableView dequeueReusableCellWithIdentifier:@"Cell1" forIndexPath:indexPath];
is returningnil
. Did you register the cell for that index path? Did you register it with the nameCell1
? -
Tarek Hallak about 10 yearsAs @rmaddy mentioned in his comment you need to do some debugging, check why your cell is nil, most likely the Cell Identifier, start from there.
-
JuanM. about 10 yearsOr could it be a storyboard problem ? I have my table view with content of "static cells" with sections equals to "2" in Storyboard editor. And the first section with its only cell is registered as Cell1 in its identifier.
-
rmaddy about 10 yearsNone of these changes are needed and it actually makes the code more confusing. And none of it fixes the problem.
-
Tarek Hallak about 10 yearsFirst the table is not a "static cells" content which has nothing to do with your problem (ignored I guess), second you need to create a prototype cell for section 2 and register it as "Cell" or init it inside your
cellForRowAtIndexPath
. -
Charan Giri about 10 years@rmaddy which part of code made you confused? return 0; means you are returning nil to cell and rows...
-
JuanM. about 10 yearsOk, that is helping. Now I do not get any error message. But I got another problem, my first custom cell has the size of the second custom cell.
-
rmaddy about 10 yearsI'm not confused. The
return
is never reached. The table has two sections. Thereforecase 0
andcase 1
of theswitch
handles the two sections. Both create and return a cell. Thedefault
is never reached. Thereturn
at the end of the method is never reached. The OP's code is much cleaner than your proposal. -
Tarek Hallak about 10 yearsGlad for that, man the cell height is another story, change it using the delegate:- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexpathe.section == 0 && indexpathe.row == 0) return 50.0; return 100; }
-
JuanM. about 10 yearsThank you Charan, but I already solved part of my problem in the answers before. I got what you say @rmaddy about the return is never reached.
-
JuanM. about 10 yearsAwesome! That really worked! I just compared the values that I had to return with the heights that I had made in the storyboard editor! Thanks a lot to you @null and rmaddy.
-
JuanM. about 10 yearsI think the use of XIB files is outdated, and with xCode 5 and iOS 7 everything works with storyboard.
-
JuanM. about 10 years
-
Charan Giri about 10 years@rmaddy when switch conditions are true The default is never reached. will it? in section 0 and 1 i'm assigning cell1 to cell and cell2 to cell and returning it at the end as return cell; break is used to just break the switch not the cell configure method. so it will reach return cell statement. If i'm wrong on this can you please explain it
-
rmaddy about 10 yearsSorry, I was talking about the OP's code. My whole point is that your suggested change is unnecessary as well as more complicated. And more importantly, it in no way solves the problem.
-
Jissay about 10 yearsI actually work with XIB files for creating cells, loading is simplier and focusing better when working on your cell design. But i understand you want to use only Storyboard Maybe you should still give it a try.
-
Gourav Gupta about 10 yearsyou can do the same thing with the help of storyboard. In case of storyboard you have to get cell's nib from your storyboard file.