TableView with multiple prototype cells - ios

I had a simple question regarding a table view with 3 different kinds of prototype cells. The first two occur just once while the third occurs 4 times. Now what I'm confused about is how to specify in my cellforRowatindexpath which cell prototype to use for which row. So, I want something like for row 0, use prototype 1, for row 1, use prototype 2, for rows 3,4,5 and 6 use prototype 3. What's the best way to do this? Do i give each prototype an identifier and then use dequeueReusableCellWithIdentifier:CellIdentifier ?
Can you'll provide some sample code?
EDIT:
Still not working. This is the code I have at the moment. ( I only have one case for the switch statment because I just want to test and see if the cell is being generated in the first row or not, but currently table view is blank)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch(indexPath.row)
{
case 0: {static NSString *CellIdentifier = #"ACell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"ACell"];
if(cell==nil) {
cell=[[UITableViewCell alloc]
initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:#"ACell"];
}
return cell;
break;
}
}
}
Acell is my identifier for a cell prototype that I created. I

If you are using three prototype then use three identifiers. Because only one identifier will cause problem. And you will get wrong result. So code like this.
if(indexPath.row==0){
// Create first cell
}
if(indexPath.row==1){
// Create second cell
}
else{
// Create all others
}
You can use switch case also here for best performance.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell.tag == 0)
{
return array1.count;
}
else(cell.tag == 1)
{
return array2.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier;
NSString *membershipType = [membershipTypeArray objectAtIndex:indexPath.row];
if ([membershipType isEqualToString:#"silver"]||[membershipType isEqualToString:#"gold"])
{
cellIdentifier = #"cell";
}
else if ([membershipType isEqualToString:#"platinum"])
{
cellIdentifier = #"premiumCustomCell";
cell.customCellImageView.image = [cellImageArray objectAtIndex:indexPath.row];
}
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.headingLabel.text = [titleArray objectAtIndex:indexPath.row];
}

Here i wrote code like:
#pragma mark == Tableview Datasource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger nRows = 0;
switch (section) {
case 0:
nRows = shipData.count;
break;
case 1:
nRows = dataArray1.count;
break;
default:
break;
}
return nRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = #"cellIdentifier1";
NSString *cellIdentifier1 = #"cellIdentifier2";
SingleShippingDetailsCell *cell;
switch (indexPath.section) {
case 0:
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//Load data in this prototype cell
break;
case 1:
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier1];
//Load data in this prototype cell
break;
default:
break;
}
return cell;
}

Related

Can I add cell dynamically in static-cell-UITableView? [duplicate]

This question already has answers here:
UITableView: Handle cell selection in a mixed cell table view static and dynamic cells
(6 answers)
Closed 7 years ago.
I'm using a UITableView to show sth,and the information in section 1,section 2 will not change,but section 3 is dynamic.
Is there any way to show section 1&2 using static cell,but I can write the datasource of section3?
Here you will get as per your requirement.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0 || section == 1) {
return 1; //However many static cells you want
} else {
return [_yourArray count];
}
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
if (indexPath.section == 0 || indexPath.section == 1 ) {
NSString *cellIdentifier = #"staticCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = #"some static content";
return cell;
} else if (indexPath.section == 1){
NSString *cellIdentifier = #"dynamicCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [_yourArray objectAtIndex:indexPath.row];
return cell;
}
return nil;
}
You can easily do like this....
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3; //number of section
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch(section){
case 0:
return 1; //static value as per your requirement
break;
case 1:
return 1; //static value as per your requirement
break;
case 2:
return [yourArray count]; //static value as per your requirement
break;
default
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CELL";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (indexPath.section == 2) {
NSDictionary *dict = [yourArray objectAtIndex:indexPath.row];
}
//If you perform any task for other section then you can write in switch case
return cell;
}

Return cells with different cell identifiers

I have a custom cell with multiple cell Identifiers. I tried the following code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellID;
switch ([indexPath section]) {
case 0:
cellID = #"firstCell";
break;
case 1:
cellID = #"secondCell";
break;
default:
break;
}
customCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
return cell;
}
When I run the app, it displays the first cell 2 times, even though in the storyboard, there are 2 cells with different objects inside.
Is [indexPath section] really what you want?
I think you want [indexPath row]

How to work with two different custom cells in one tableView ? Using Storyboard, iOS 7

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!
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...
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.
you can create set of cell in one xib and fetch it in cellForRowAtindex with it's identifier. Now you can set it's property and data to it.
static NSString *CellIdentifier = #"MyCellIdentifier";
MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (MyCell *)[nib objectAtIndex:0];
cell1=(MyCell *)[nib objectAtIndex:1];
}
Try This i'm modifying your 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 == 2) {
//gastos is an array
return [self.gastos count];
}
//return 0; you should not write this because at the end of execution of this method it will return 0
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
switch (indexPath.section) {
case 0:
{
SaldoCelda *cell1 = [tableView dequeueReusableCellWithIdentifier:#"Cell1" forIndexPath:indexPath];
cell=cell1;
break;
}
case 1:
{
static NSString *CellIdentifier = #"Cell";
CeldaGasto *cell2 = [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"]]];
cell=cell2;
break;
}
default:
break;
}
return cell;
//return 0; remove this in your code
}
Hope this will help

Set different row height in different sections (storyboard)

I have a tableview with multiple prototype cells that i designed in the storyboard, but i´m stuck with the height problem because my first cell is supose to be different from the second one and so on...I have different identifiers for each cell, and because i designed them in storyboard, i know they´re height´s. I have this in my code, but it´s not working, does anyone knows how to fix it?:
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc]init];
switch (indexPath.section)
{
case 1:
cell = [tableView dequeueReusableCellWithIdentifier:#"cell1"];
return 743.0f;
break;
case 2:
cell = [tableView dequeueReusableCellWithIdentifier:#"cell2"];
return 300.0f;
}
}
Thanks for your time.
It looks like you are trying to use this method for purposes it wasn't designed for...
you'll want to override the method:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section)
case 1:
static NSString *CellIdentifier = #"cell1";
break;
case 2:
static NSString *CellIdentifier = #"cell2";
break;
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
return cell;
}
Only change the row height in the heightForRowAtIndexPath:
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section)
{
case 1:
return 743.0f;
break; //technically never used
case 2:
return 300.0f;
}
Check out this tutorial http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1 its a good resource

How to make a section show all the content? (in a UITableView)

I am playing with a piece of code and this is what I have gotten so far. The app gets an XML feed to display job advertisements, and shows them as in the images I attached.
What I am trying to figure out is, how to make the "Description" part display all the information taken from the XML file.
Would the answer be hidden in changing something in this method?
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
switch(indexPath.section)
{
case 0:
cell.text = aBook.title;
break;
case 1:
cell.text = aBook.author;
break;
case 2:
cell.text = aBook.summary;
break;
}
return cell;
}
Try to implement this:
-(CGFloat ) tableView:(UITableView*) tableView heightForRowAtIndexPath:(NSIndexPath*) indexPath
{
If(indexPath.section==2)
{
return 60;
}
}

Resources