为每个UITableViewCell设置UIButton.imageView.image

时间:2012-10-01 16:34:46

标签: ios xcode uitableview

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

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

- (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是零,我已经尝试过没有它,但最近刚补充说是尝试修复。

我基本上是建立一个消息列表(收件箱),并希望像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调用都是多余的,我大多只是让它们在那里展示什么不起作用。只有reloadData至少会重绘/刷新每个单元格,即使大多数示例都说单元格上的setNeedsLayout应该有效。

单击时复选框的更改会发生什么变化,但是如果我勾选一个单元格,则单击以突出显示单元格,取消选中该复选框,直到视图在屏幕外滚动然后再返回。我认为问题与选择vs未选择的视图有不同,但除此之外不确定要检查的内容。

编辑由于大多数教程都使用与此类似的代码,这也是我也尝试过的,但在这种用法中,图像永远不会改变,直到单元格在屏幕上滚动并返回,即使我可以设置断点,并在我的点击事件中调用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;
}

2 个答案:

答案 0 :(得分:1)

不确定这是否是一个好的答案,但它似乎有效,也许是Apple打算做的事情。

我从另一个SO答案UITableViewCell Reuse and Images Re-render得到了这个想法,他们为每种不同的风格使用了多个原型。

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

- (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控件中的不同图像。我读过有关人们发现某些属性(如背景颜色和字体样式)的问题,所以这可能只是这些问题的另一个问题。

答案 1 :(得分:0)

你试过吗

- (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;
}

不使用tableView:willDisplayCell:forRowAtIndexPath:?然后在每次调用时调用[self.tableView reloadData];,导致tableView刷新并为所有可见索引路径调用cellForRowAtIndexPath: ...