記錄一次奇怪的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

相關文章
相關標籤/搜索