Ios 为每个UITableViewCell设置UIButton.imageView.image

Ios 为每个UITableViewCell设置UIButton.imageView.image,ios,xcode,uitableview,Ios,Xcode,Uitableview,我使用interface builder创建了一个自定义单元格,它有两个标签和一个UIButton。我可以在CellForRowatineXpath或willDisplayCell中设置每个标签的文本。但是,设置UIButton的图像在这两个地方都有问题。我认为这些问题与我不完全理解的单元重用/缓存有关 以下是我当前主要使用willDisplayCell的代码,但我也尝试将大部分代码移动到CellForRowatineXpath,结果相同: - (void)tableView:(UITableV

我使用interface builder创建了一个自定义单元格,它有两个标签和一个UIButton。我可以在CellForRowatineXpath或willDisplayCell中设置每个标签的文本。但是,设置UIButton的图像在这两个地方都有问题。我认为这些问题与我不完全理解的单元重用/缓存有关

以下是我当前主要使用willDisplayCell的代码,但我也尝试将大部分代码移动到CellForRowatineXpath,结果相同:

- (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;
}
在上面的代码中,check2是nil,我也尝试过不使用它,但最近刚刚添加了它作为修复的尝试

我基本上是建立一个邮件列表(收件箱),并希望像GMail一样的复选框。在复选框按钮的单击事件中,我有:

- (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];
}
我知道上面所有的setNeedsLayout和setNeedsDisplay调用都是多余的,我通常只是把它们放在那里,以显示哪些不起作用。只有重新加载数据至少会重新绘制/刷新每个单元格,即使大多数示例都说单元格上的setNeedsLayout应该起作用

当单击时,复选框会正确更改,但是如果我选中一个单元格,然后单击以突出显示该单元格,则复选框将被取消选中,直到视图滚动到屏幕外,然后返回。我假设问题与“选定”和“未选定”存在不同的视图有关,但除此之外,我不确定要检查什么

编辑:由于大多数教程使用与此类似的代码,我也尝试了以下方法,但在这种用法中,图像在单元格被滚动到屏幕上之前不会改变,即使我可以设置断点,并看到在单击事件中调用reloadData后,会再次为每个单元格调用cellForRowAtIndexPath,对于我选中的项目,它正确地将图像设置为选中:

- (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;
}
你试过了吗

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = nil;
    // Try to dequeue
    cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    // If nothing to dequeue, create your CustomCell
    if(!cell){
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:nil options:nil];
        for(id currentObject in topLevelObjects){
            if([currentObject isKindOfClass:[CustomCell class]]){
                cell = (CustomCell *)currentObject;
                break;
            }
        }
    }
    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;
    return cell;
}

不使用
表格视图:willDisplayCell:forrowatinexpath:
?然后每次单击
[self.tableView reloadData],导致tableView刷新并调用
cellforrowatinedexpath:
用于所有可见的索引路径…

不确定这是否是一个好的答案,但它似乎可以工作,并且可能是Apple预期的方式

我是从另一个SO答案中得到这个想法的,他们为每种不同的风格使用了多个原型

所以我在IB中创建了两个原型单元,一个带有选中图像,另一个带有未选中图像。然后将我的代码更新为:

- (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
{
    Message *rec = (Message*) Records[indexPath.row];

    UITableViewCell *cell;
    if(rec.Checked)
        cell = [tableView dequeueReusableCellWithIdentifier:@"CheckedCell"];
    else
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

    UILabel *from = (UILabel*) [cell.contentView viewWithTag:2];
    UILabel *subject = (UILabel*) [cell.contentView viewWithTag:3];

    from.text = rec.From;
    subject.text = rec.Subject;

    return cell;
}

我能想到的只是“重用”单元支持某些更改,但不支持其他更改。因此,它支持UILabel控件中的不同文本,但不支持UIButton控件中的不同图像。我曾读到有人发现某些属性(如背景颜色和字体样式)存在问题,因此这可能只是这些方面的另一个问题。

是的,但为了确保我现在会重试,因为代码有点变化……我将刚尝试过的代码添加到我的原始帖子中,结果不同,但仍然不起作用。在我的代码中,dequeueReusableCellWithIdentifier从不返回null,我认为这是应该的,因为单元格是在IB中定义的,而不是在运行时添加的。也许这就是问题所在,不确定,但是添加额外的代码应该不会有帮助,因为它在我的情况下永远不会运行,因为从不为NULL。我只是看到了你的编辑,但我不明白。您的意思是clickEvent有效地改变了图像,同时您必须上下滚动才能看到效果?CheckClicked函数中的重载数据调用导致对每个可见单元格再次调用cellForRowAtIndexPath,通过调试器可以正确地显示我的代码,设置选中/未选中的图像,但iOS 6.0模拟器上的显示没有更新。所以我的代码似乎工作正常,但结果并不是我所期望的。哦,我明白了。所有对象都将更新,但显示屏上没有任何更改。真倒霉我相信你的变通办法是我当时唯一能想到的办法,对不起!