龙空技术网

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

爱音乐的程序员小新人 50

前言:

如今咱们对“自适应高度”都比较关注,你们都想要剖析一些“自适应高度”的相关内容。那么小编同时在网摘上汇集了一些关于“自适应高度””的相关文章,希望你们能喜欢,各位老铁们一起来学习一下吧!

下面是我的情况:设置一个空白cell,通过cellModel的height属性动态设置高度。

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.

仔细看

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

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

有冲突导致系统约束警告。 这里我们把断点放过,可以看到视图还是按我们预想的展示的,但是警告总让人不爽,那么尝试来解决这个问题。

问题分析:

新的约束UIView:0x7f9cfe5189f0.height == 21 试图破坏 UITableViewCellContentView:0x7f9cfe518800.height == 28回想一下,上一次我们设置的是约束应该UIView:0x7f9cfe5189f0.height == 28,但是UIView:0x7f9cfe5189f0还有另外2个约束就是上下贴着UITableViewCellContentView,所有间接导致UITableViewCellContentView:0x7f9cfe518800.height == 28。这个时候试图破坏原来的约束就会导致约束冲突。另外可以猜想UITableViewCellContentView:0x7f9cfe518800.height == 28这条约束应该是UITableView组件给附加上的,因为我们本身没有写这句话。既然这条约束是系统维护的,他就会在一定时候维护这条约束。不会提前,那就只有延后,在cellForRow之后发生,而我们改变约束是在cellForRow的时候。

解决方法

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

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

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

注:不设置priority默认是MASLayoutPriorityRequired

- (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约束,当布局改变化,这个属性也会改变。 为了不和系统冲突,我们只有适当降低自身约束的优先级

标签: #自适应高度