I created a custom cell using interface builder, it has two labels and one UIButton. I have no problem setting the text of each label inside cellForRowAtIndexPath or willDisplayCell. However, setting the image of the UIButton has issues in either place. I think the issues are related to cell re-usage/caching that I don’t fully understand.
Here is my current code that mostly uses willDisplayCell, but I have also tried moving most of the code to cellForRowAtIndexPath with the same results:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIButton *check = (UIButton*) [cell.contentView viewWithTag:1];
UIButton *check2 = (UIButton*) [cell.selectedBackgroundView viewWithTag:1];
UILabel *from = (UILabel*) [cell.contentView viewWithTag:2];
UILabel *subject = (UILabel*) [cell.contentView viewWithTag:3];
// Configure the cell...
Message *rec = (Message*) Records[indexPath.row];
if(rec.Checked)
check.imageView.image = [UIImage imageNamed:@"Checkedbox.png"];
else
check.imageView.image = [UIImage imageNamed:@"Checkbox.png"];
check2.imageView.image = check.imageView.image;
from.text = rec.From;
subject.text = rec.Subject;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
return cell;
}
In the above code, check2 is nil, I’ve tried without that as well, but just recently added that as an attempt to fix.
I’m basically building a message list (inbox) and want checkboxes like GMail has. In the click event for the checkbox button I have:
- (IBAction)CheckClicked:(id)sender
{
UITableViewCell *cell = (UITableViewCell*) [[sender superview] superview];
NSIndexPath *indexPath = [[self tableView] indexPathForCell:cell];
Message *rec = (Message*) Records[indexPath.row];
rec.Checked = !rec.Checked;
[cell setNeedsLayout];
[cell.contentView setNeedsLayout];
[cell setNeedsDisplay];
[cell.contentView setNeedsDisplay];
[self.tableView reloadData];
}
I know all of the setNeedsLayout and setNeedsDisplay calls above are redundant, I mostly just have them there to show what didn’t work. Only reloadData would at least redraw/refresh each cell, even though most examples say setNeedsLayout on the cell should have worked.
What happens is the checkboxes change correctly when clicked, however if I checkmark one cell, then I click to highlight the cell, the checkbox is unchecked until the view scrolls off-screen and then back. I assumed the problem is related to there being different views for selected vs not-selected, but beyond that not sure what to check.
Edit: As most tutorials use code similar to this, here is what I have also tried, but in this usage the image never changes until cells are scrolled off and back on screen, even though I can set breakpoints and see that the cellForRowAtIndexPath is being called for each cell again after reloadData is called in my click event, and it is correctly setting the image to checked for the item I checked:
- (IBAction)CheckClicked:(id)sender
{
UITableViewCell *cell = (UITableViewCell*) [[sender superview] superview];
NSIndexPath *indexPath = [[self tableView] indexPathForCell:cell];
Message *rec = (Message*) Records[indexPath.row];
rec.Checked = !rec.Checked;
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
// NOTE: In my testing cell is never NULL, so I have no checking here.
UIButton *check = (UIButton*) [cell.contentView viewWithTag:1];
UILabel *from = (UILabel*) [cell.contentView viewWithTag:2];
UILabel *subject = (UILabel*) [cell.contentView viewWithTag:3];
// Configure the cell...
Message *rec = (Message*) Records[indexPath.row];
if(rec.Checked)
check.imageView.image = [UIImage imageNamed:@"Checkedbox.png"];
else
check.imageView.image = [UIImage imageNamed:@"Checkbox.png"];
from.text = rec.From;
subject.text = rec.Subject;
return cell;
}
Not sure if this is a good answer, but it appears to work and maybe is the way Apple intended for things to be.
I got the idea from another SO answer UITableViewCell Reuse and Images Re-render where they used multiple prototypes for each different style.
So instead I created 2 prototype cells in IB, one with the checked image, and one with the unchecked image. Then updated my code to this:
All I can figure is the “reused” cell supports certain changes, but not others. So it supports different text in UILabel controls, but does not support different images in UIButton controls. I have read about people finding issues with certain properties like background colors and font styles, so maybe this is just another issue along those lines.