ios - 为每个 UITableViewCell 设置 UIButton.imageView.image

标签 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 调用都是多余的,我大多只是让它们在那里显示什么不起作用。尽管大多数示例都说单元格上的 setNeedsLayout 应该有效,但只有 reloadData 至少会重绘/刷新每个单元格。

发生的情况是,单击时复选框会正确更改,但是如果我选中一个单元格,然后单击以突出显示该单元格,则该复选框将处于取消选中状态,直到 View 滚动到屏幕之外然后再返回。我认为问题与选定与未选定的 View 不同有关,但除此之外不确定要检查什么。

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

最佳答案

不确定这是否是一个好的答案,但它似乎有效,而且也许就是苹果想要的方式。

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

因此,我在 IB 中创建了 2 个原型(prototype)单元,一个包含已检查的图像,另一个包含未检查的图像。然后将我的代码更新为:

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

关于ios - 为每个 UITableViewCell 设置 UIButton.imageView.image,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12677364/

相关文章:

iOS 应用程序 - 当用户从设备中删除应用程序时进行拦截

ios - 如何在我的代码中使用默认的 LoginWithFacebook 按钮

ios - 如何检查刷新控件是否在其目标操作方法中刷新

ios - Swift:类型 'ViewController' 不符合协议(protocol) 'UIPageViewControllerDataSource'

ios - 稍后在应用程序中使用 prepareForSegue 将数据传递给 ViewController

Swift 4 SVProgressHUD 未在加载时显示

swift - iOS 9.3 Today View 高度受限

ios - UITableViewCell 内的可滚动 StackView - ScrollView ContentSize 未更新

iOS:我可以在 APP 商店中分发不同国家/地区的不同 .ipa 文件吗

ios - 编程 .beginRefresh() 不刷新 UITableView 中的数据