关于单元重用的自定义UITableViewCell约束问题

时间:2016-01-27 04:37:20

标签: ios objective-c uitableview autolayout

我有一个自定义UITableViewCell,它具有动态图像高度。所有的大小调整都是在创建单元格时所应用的。问题是一旦单元格被UITableView重用,图像高度的约束就会发生变化,并导致“无法同时满足约束”错误。

我尝试在重置之前停用高度限制,但仍会导致错误。

关于设置高度锚。这会每次创建一个新实例,是从内存中释放的已停用约束吗?有没有办法只更新这种格式的当前约束?

我应该在 - (void)prepareForReuse方法中做些什么吗?

感谢您的帮助

// Within Custom UITableViewCell
// The cell is a prototype cell in StoryBoard
// The width of the image is fixed and already set
// Observe when the image is set for imgView

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {

if ([keyPath isEqualToString:@"image"]) {
    if(self.imgView.image) {

        CGFloat ratio = self.imgView.image.size.height / self.imgView.image.size.width;
        self.imageHeightConstraint.active = NO;
        self.imageHeightConstraint = [self.imgView.heightAnchor constraintEqualToAnchor:self.imgView.widthAnchor multiplier:ratio];
        self.imageHeightConstraint.identifier = @"imageHeightConstraint";
        self.imageHeightConstraint.active = YES;

    }
}

}

UITableViewCell自动调整大小UIImageView位于UIStackView,其顶部和底部锚点固定在单元格contentView的顶部和底部。

- (void)buildUI {

    UIStackView *containerStackView = [UIStackView new];
    [self.contentView addSubview:containerStackView];
    containerStackView.translatesAutoresizingMaskIntoConstraints = NO;
    containerStackView.axis = UILayoutConstraintAxisHorizontal;
    containerStackView.distribution = UIStackViewDistributionFill;
    containerStackView.alignment = UIStackViewAlignmentCenter;
    containerStackView.spacing = 10;
    [containerStackView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:10.0].active = YES;
    [containerStackView.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor].active = YES;
    [containerStackView.widthAnchor constraintEqualToAnchor:self.contentView.widthAnchor multiplier:kImageWidthMultiplier].active = YES;
    [containerStackView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-30.0].active = YES;

    self.imgView = [UIImageView new];
    [containerStackView addArrangedSubview:self.imgView];
    self.imgView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.imgView.widthAnchor constraintEqualToAnchor:containerStackView.widthAnchor multiplier:0.492].active = YES;
}

1 个答案:

答案 0 :(得分:0)

计算动态表格视图单元格高度非常复杂。在您的情况下,单元格高度取决于图像高度。

当重复使用表格视图单元格时,将重用所有单元格的属性,并且高度不是异常。进行更改的简单方法是使用heightForRowAtIndexPath,但使用autolayout计算高度时非常困难。

根据这篇文章(http://www.raywenderlich.com/87975)。表视图单元格中的子视图将被压缩,之后,我们可以轻松获得高度并返回heightForRowAtIndexPath。但是,它需要一些时间来计算并使您的滚动不顺畅,但我们可以使用estimatedRowHeight,您的tableview将使用估计高度并申请特定行,然后我们才能计算出该行的确切高度

以下是简短的演示代码:

//Estimate height (height could be 35, 42, 50, 29, etc)
//Just estimate a number
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        return 40.0f;
}

//Your exactly height for row
- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
    [yourCustomCell setNeedsLayout];
    [yourCustomCell layoutIfNeeded];

    CGSize size = [yourCustomCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    return size.height;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //only set once
    static YourCustomTableViewCell *yourCustomCell = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //load custom cell
        yourCustomCell = (YourCustomTableViewCell*)[Utils getCellNibFile:@"YourCustomTableViewCell" Owner:self];
});
    //get image from datasource
    UIImage* image = [self.dataSource objectAtIndex:indexPath];
    //set image for cell and begin calculate height after set image
    [yourCustomCell setImage:image];
    [self calculateHeightForConfiguredSizingCell:yourCustomCell];
    return height;
}