Use two different cell identifier on same table view - iphone

I'm trying to get rid of a cached UITableView cell. I have two sections. The first cell of the second section has the same "appearance" as the first cell of the first section. With appearance I mean the cell height (multiline cells).
I tried to use different identifiers, but that didn't worked. Here is the code:
NSString *identifier;
if (thisViewMode) {
identifier = #"thisViewMode";
} else if ((indexPath.section == 1) && thatViewMode) {
identifier = #"thatViewMode";
} else {
identifier = #"CellIdentifier";
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [self CreateMultilinesCell:identifier];
}
thatViewMode is only called once, which isn't right because I have more cells in my second section. If I change the content of the first cell in the first section, the height of the first cell in the second section also changes too. Normally each cell should have it's own cell height, but that isn't the case here.
Is there a problem that I can't use different cell identifiers on the same table view?

I forgot to also adapt heightForRowAtIndexPath so that I make a differentiation between the sections.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 1) {
// do something
} else {
// do something different
}
return ...
}

Related

Two UITableViewCell with different identifier and different height in storyboard

I have two type of cells that I'll be using my UITableView, so I created two prototype cell with different identifier. I manuelly changed the size but when I compile and run, the two cells have same size.
Is there any way to do it through storyboard and without checking every single time
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
I will have around a good 100 cells at least.
UPDATE: in my case I have a tableview with 3 sections, the first one is small, the second and the third one are bigger.
I think your best option is to use that -tableView:heightForRowAtIndexPath: delegate method you listed and return the height you would like.
You could assign tags to each prototype and use an if/else if conditional.
Or if you have a subclassed UITableViewCell for each prototype you could do something like
...
id cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[CustomCell1 class]]) {
// return aNumber;
} else if ([cell isKindOfClass:[CustomCell2 class]]) {
// return aNumber;
} else {
return aNumber;
}
...
If you know that the sections if what determines the height of the cell, then you can implement it like this:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath {
CGFloat result;
if (indexPath.section == 0) {
result = 160;
} else {
result = 80;
}
return result;
}
Depending on the heights that you need of course.

Don't display empty grouped cell tableview

I'm doing a similar view to View Contact in Contacts.app, meaning I have multiple fields that are not required (second work phone, second email, etc.) under different sections (Phones, Emails, etc.).
When some fields are empty, I don't want to display them, when all the fields are empty under a section, I don't want to display this section. Also, some of the cells have action on them, like when tapping on a phone number cell, it calls the number displayed. Currently, these actions are manually handled in didSelectRowAtIndexPath with basic ifs depending of the cell position.
I can't find an elegant solution to do all this... I tried an array of dictionaries (each cell) for each section but things rapidly went messy. Also, since the order of the rows is never the same, I can't easily with ifs handle all the actions in the didSelectRowAtIndexPath method based on the cell position.
Oh and I'm using Core Data under the hood.
Anybody had to do something similar and is willing to share his thoughts?
Thanks!
Exemple of my static ifs setup right now to differentiate cells:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (indexPath.section == 0)
{
// Custom actions here
}
else if (indexPath.section == 1)
{
// Other actions here
[self showMailComposeWithEmail:cell.textLabel.text];
}
}
And another method using indexPath to differentiate styles and behaviors:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if (indexPath.section == 0)
{
if (indexPath.row == 0)
{
cell.textLabel.text = self.contact.phone;
}
}
else if (indexPath.section == 1)
{
if (indexPath.row == 0)
{
cell.textLabel.text = self.contact.email;
}
}
return cell;
}
Take a dictionary and when you add object to that dictionary make sure that the data in it is not blank. Add it data in dictionary for keys as below:
Phones - key 0^0 (it means at 0 section 0 row)
WorkPhone - key 0^1(it means at 0 section 1st row)
Emails - key1^0 (1 section 0th row) and so on...
And at cellForRowAtIndexPath fetch this value as
[dict valueForKey:[NSString stringWithFormat:#"%d^%d",indexPath.section,indexPath.row]];
Hope thats clear.

how can we set different tag values to each cell in tableview in iphone

i am new to iphone. i want to set different tag values to each cell in table view.for example I have a table view with 6cells.Here i want to set tag value to 1st cell is 4 and tagvalue to 2nd cell is 1 like that for all 6 cells we have to set 6 different values.
If any body know this please help me...
you can set the like this...
cell.tag = indexPath.row + 1..
it will set your cell tag as 1 to 6...
may this will help you
You may set the tag value within the TableViewControler's cellForRowAtIndexPath method. There you should have all data available, that is known to the view controller and you have access to each cell that is about to be displayed.
As UITableViewCell inherits from UIView just type
cell.tag = value; //with value being what you want to assing in this case.
If you are having fixed number of cells, you can do this in cellForRowAtIndexPath by checking each cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (indexPath.row == 0) {
cell.tag = 4;
}
else if(indexPath.row == 1)
{
cell.tag = 1;
}
else if(indexPath.row == 2)
{
...so on
}
return cell;
}

UITableview mixes up cells

i have a problem with my UITableview. After scrolling or pushing the switch it starts sometimes mixing up the cells. So you can so the text of one cell shows up in the other. I read a lot about tableViews, but I found nothing that fits for my code.
Here it is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
if (indexPath.section == 0) {
if (indexPath.row == 0) {
cell.textLabel.text = NSLocalizedString(#"Course:",#"Course Section");
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.detailTextLabel.text = entryTableCourseName;
}
else if (indexPath.row == 1) {
cell.textLabel.text = #"Due Date:";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.detailTextLabel.text = entryTableDueDateString; }
}
else if (indexPath.section == 1) {
if (indexPath.row == 0) {
//cell.textLabel.text = NSLocalizedString(#"Title", #"entryTableTaskTitle");
[cell.contentView addSubview:nameField];
}
else if (indexPath.row == 1) {
[cell.contentView addSubview:TaskView];
}
}
else if (indexPath.section == 2) {
if (entryTableGradeSwitch.on) {
if (indexPath.row == 0) {
cell.textLabel.text = NSLocalizedString(#"Grading", #"GradingCell");
cell.accessoryView = entryTableGradeSwitch;
}
else if (indexPath.row == 1) {
cell.textLabel.text = NSLocalizedString(#"Options", #"GradingCellOptions");
}
}
else {
cell.textLabel.text = NSLocalizedString(#"Grading", #"GradingCell");
cell.accessoryView = entryTableGradeSwitch;
}
}
}
I feel like I'm doing something really wrong on setting up the cells.
It's all due to cell-reusability. There are plenty of posts about this on StackOverflow, and I would recommend that you search for "UITableViewCell Reusability Problems", and you will come across the solution.
In short .. What happens here is that when you are scrolling, the cell essentially re-uses the one used before at that indexPath, and cellForRowAtIndexPath assigns a different cell at that indexpath.
Solution ?
Use different reuse identifiers for each cell.
Subclass your tableViewCell with the view or label that is getting messed up.
Make sure you implement
- (void) prepareForReuse
in your cell if you reuse them. In this routine clean up anything you added to the cell that you don't want to show up in another reuse. If you don't add any custom items just make sure when you populate a cell that you set everything even if it's empty.
Every time you do this:
[cell.contentView addSubview:TaskView]
Or something like it, you are adding a new subview to the cell. As the cells get reused, you add more and more subviews.
From your code, it isn't even clear where nameView and taskView come from. They should be either added once when a cell is first created, and just configured thereafter, or they should be part of your cell as designed in the xib or storyboard.
Here's a super-simple fix for this, and you still get to keep your reuse-identifiers! Also no subclassing or anything needed.
It's simple: just make sure and set all of your labels and views. This means that if one cell isn't going to use the detail text label, still set it to #"". By doing this, you make sure that no leftover data from the content that used the cell before is still there.
Super simple, and works every time! Also way better resource wise than not reusing your cells.

Using multiple cell style types and custom cells in a UITableView

I'm having problems figuring out how to display different cell styles as well as custom cells together within a UITableView. I understand how to set up and put cells together and the construction of a basic UITableView, but just not how to "mix and match" cell within one.
The best example I can show you on what I am trying to achieve is with the Tweetie 2 application.
The top of the segment there is a block paragraph, then below it there UITableViewCell's with the UITableViewCellStyleValue2 style set. How exactly would I go about achieving this effect?
Thanks ahead of time
The main layout is a grouped table. Each cluster of cells is a table section. The top most cell is set with a transparent background.
The key to making this work is to have a logical structure in the tableview delegate that understands which cell layout goes in which section and which row. A switch statement is usually easiest although you can also use arrays or dictionaries configure to reflect the layout.
So, in tableView:cellForRowAtIndexPath: you would have something like:
switch (indexPath.section) {
case 0:
cell= //configure cell with transparent background
break;
case 1:
if (indexPath.row==0) {
cell = // configure cell for multiline
}else {
cell = // configure for UITableViewCellStyleValue2
}
break;
case 2:
// .. and so on for each section and cell
break;
default:
break;
}
In this layout, the tableview is being used less as a logical table (which displays repeating units of list structured data) and more as convenient mechanism for managing a layout. The logic managing the tableview has to be more complex and reflect the needs of the layout.
The most direct approach would be to change your implementation of -tableView:cellForRowAtIndexPath: to use indexPath.section and indexPath.row to determine which type of cell to draw. For example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
if (indexPath.row == 0) {
// return long text style cell
} else {
// return left/right label style cell
}
} else {
// return the 4-way button style cell
}
}
Depending on how many cells you are rendering and how many cell styles you've got, you may need to re-use cells in which case you should use a different cell identifier for each style of cell.
This is an elegant way to do:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
/*
Call a function to create all custom cells.
Send the tableview and the indexPath to this function.
So, your code will be clean and easy to read an maintenance =D
DON'T forget to change the height of each cell
*/
if (indexPath.row < 3)
return [self createACustomCell1:tableView indexPath:indexPath];
else
return [self createACustomCell2:tableView indexPath:indexPath];
}
//*************
// Create CUSTOM CELL 2
//*************
-(UITableViewCell *)createACustomCell1:(UITableView *)anTableView indexPath:(NSIndexPath *)indexPath{
static NSString *CUSTOMCELL_1 = #"CUSTOMCELL_1";
CustomCell_1 *cell = [anTableView dequeueReusableCellWithIdentifier:CUSTOMCELL_1];
if (!cell){
[anTableView registerNib:[UINib nibWithNibName:CUSTOMCELL_1
bundle:nil] forCellReuseIdentifier:CUSTOMCELL_1];
cell = [anTableView dequeueReusableCellWithIdentifier:CUSTOMCELL_1];
}
// Cell customization above
return cell;
}
//*************
// Create CUSTOM CELL 2
//*************
-(UITableViewCell *)createACustomCell2:(UITableView *)anTableView indexPath:(NSIndexPath *)indexPath{
static NSString *CUSTOMCELL_2 = #"CUSTOMCELL_2";
CustomCell_2 *cell = [anTableView dequeueReusableCellWithIdentifier:CUSTOMCELL_2];
if (!cell){
[anTableView registerNib:[UINib nibWithNibName:CUSTOMCELL_2
bundle:nil] forCellReuseIdentifier:CUSTOMCELL_2];
cell = [anTableView dequeueReusableCellWithIdentifier:CUSTOMCELL_2];
}
// Cell customization above
return cell;
}
To get the same effect as Tweetie's split cell, create a custom cell and add a Segmented Control and create title and detail labels