记录一次奇怪的UITableCell自适应高度bug经历

问题@iOS-zhouyu相似 https://blog.csdn.net/kuangdacaikuang/article/details/78805615git

下面是个人状况:设置一个空白cell,经过cellModel的height属性动态设置高度。github

self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;
- (void)setupSubviews {
    [self.contentView addSubview:self.line];
}

- (void)zz_bindModel:(ZZBlankAreaCellModel*)viewModel {
    self.viewModel = viewModel;
    self.line.backgroundColor = viewModel.color;

    [self.line mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.bottom.mas_equalTo(0);
        make.height.mas_equalTo(viewModel.height).priority(MASLayoutPriorityRequired);
        make.left.mas_equalTo(self.contentView).mas_offset(viewModel.lineEdgeInsets.left);
        make.right.mas_equalTo(self.contentView).mas_offset(-viewModel.lineEdgeInsets.right);
    }];
}

- (UIView *)line
{
    if (!_line) {
        _line = ({
            UIView *view = [UIView new];
            view;
        });
    }
    return _line;
}

当cell复用,高度发生变化时,会出现下面的警告。布局

2018-09-19 09:35:37.200637+0800 ZZTableView[17299:3212632] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<MASLayoutConstraint:0x6000017536c0 UIView:0x7f9cfe5189f0.top == UITableViewCellContentView:0x7f9cfe518800.top>",
    "<MASLayoutConstraint:0x600001750f60 UIView:0x7f9cfe5189f0.bottom == UITableViewCellContentView:0x7f9cfe518800.bottom>",
    "<MASLayoutConstraint:0x600001750f00 UIView:0x7f9cfe5189f0.height == 21>",
    "<NSLayoutConstraint:0x60000106b700 UITableViewCellContentView:0x7f9cfe518800.height == 28>"
)

Will attempt to recover by breaking constraint 
<MASLayoutConstraint:0x600001750f00 UIView:0x7f9cfe5189f0.height == 21>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

仔细看ui

<MASLayoutConstraint:0x600001750f00 UIView:0x7f9cfe5189f0.height == 21>

this

<NSLayoutConstraint:0x60000106b700 UITableViewCellContentView:0x7f9cfe518800.height == 28>

有冲突致使系统约束警告。 这里咱们把断点放过,能够看到视图仍是按咱们预想的展现的,可是警告总让人不爽,那么尝试来解决这个问题。.net

问题分析:

  1. 新的约束UIView:0x7f9cfe5189f0.height == 21 试图破坏 UITableViewCellContentView:0x7f9cfe518800.height == 28
  2. 回想一下,上一次咱们设置的是约束应该UIView:0x7f9cfe5189f0.height == 28,可是UIView:0x7f9cfe5189f0还有另外2个约束就是上下贴着UITableViewCellContentView,全部间接致使UITableViewCellContentView:0x7f9cfe518800.height == 28。这个时候试图破坏原来的约束就会致使约束冲突。
  3. 另外能够猜测UITableViewCellContentView:0x7f9cfe518800.height == 28这条约束应该是UITableView组件给附加上的,由于咱们自己没有写这句话。既然这条约束是系统维护的,他就会在必定时候维护这条约束。不会提早,那就只有延后,在cellForRow以后发生,而咱们改变约束是在cellForRow的时候。

解决方法

既然咱们是在bindModel改变约束,bindModel是在cellForRow被调用,这个事实不能改变。并且咱们不能维护UITableViewCellContentView:0x7f9cfe518800.height的约束(系统维护) 好,分析完了,给出解决方法:debug

下降与UITableViewCellContentView约束冲突的View的约束优先级code

上面的问题就是View.height的约束优先级下降 make.height.mas_equalTo(viewModel.height).priority(MASLayoutPriorityDefaultHigh);blog

注:不设置priority默认是MASLayoutPriorityRequiredrem

- (void)zz_bindModel:(ZZBlankAreaCellModel*)viewModel {
    self.viewModel = viewModel;
    self.line.backgroundColor = viewModel.color;

    [self.line mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.bottom.mas_equalTo(0);
        make.height.mas_equalTo(viewModel.height).priority(MASLayoutPriorityDefaultHigh);
        make.left.mas_equalTo(self.contentView).mas_offset(viewModel.lineEdgeInsets.left);
        make.right.mas_equalTo(self.contentView).mas_offset(-viewModel.lineEdgeInsets.right);
    }];
}

原理分析:

当咱们使用

self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;

系统在就会在咱们设置好视图后,自动给UITableViewCellContentView附加一个合适的height约束,当布局改变化,这个属性也会改变。 为了避免和系统冲突,咱们只有适当下降自身约束的优先级

Code

附上个人代码 https://github.com/ZiFy/ZZTableView

相关文章
相关标签/搜索