控制台输出约束警报,界面完好
现象
在这里插入图片描述发现在使用UITableView控件时候,self.tableView.tableHeaderView = self.viewHeader;控制台打印大量的约束冲突,但是界面完好。
解决办法
UIView *viewTemp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, heightUse)];
[viewTemp addSubview:self.viewHeader];
[self.viewHeader mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(viewTemp).priority(900);
}];
self.tableView.tableHeaderView = viewTemp;
问题分析
self.viewHeader.frame = CGRectMake(0, 0, ScreenWidth, heightUse);
self.tableView.tableHeaderView = self.viewHeader;
self.tableView.tableHeaderView一开始尺寸为0.后来设置self.tableView.tableHeaderView = self.viewHeader;导致runLoop的一个循环周期内self.tableView.tableHeaderView的尺寸要进行变化。从0变化到self.viewHeader的尺寸。
因为self.tableView.tableHeaderView = self.viewHeader;所以self.tableView.tableHeaderView的尺寸变化就反应在了self.viewHeader的尺寸变化上。也就是self.viewHeader的尺寸从0变化到一个设置的尺寸。
在self.viewHeader的变化中,一开始尺寸为0。这时候我们的布局有可能会有冲突。其实我们布局时候很少甚至不会考虑最底部视图布局尺寸为0,我们认为永远不会为0,都在我们的掌控中,但是tableView的头布局这种尺寸变化特性导致一开始我们的最外层视图尺寸为0。导致有约束的冲突,这时候控制台打印出了警报,而且可能有很多警告。每个警告中都有类似这种问题,xxxView.width == 0。
=="<NSLayoutConstraint:0x600001ac0140 xxxView:0x7ff534cca8a0.width == 0>"==
这种警告也反应出了父视图宽度为0 导致约束冲突。当视图展开后,我们的约束又没有冲突了,runLoop更新UI后其实又没有问题了,所以这时候界面又变现的很正常。但是其实之前确实是有约束冲突的,控制台也输出了警告信息。
看到这里其实我们知道了原因了。就是我们的自定义的视图的最外层view尺寸变为了0,这时候我们的view有约束冲突。控制台打印出了约束警告。之后当我们的视图尺寸展开后又一切正常,UI上也没任何问题。
证明
在这里插入图片描述可以看出确实self.viewHeader的尺寸从0展开。
解决办法分析
第一种办法: 利用优先级
可以看到我们解决办法是又新创建了一个viewTemp,在这个viewTemp上添加我们的self.viewHeader。在进行约束,并把优先级调到900。
这时候一开始self.viewHeader尺寸为0,这时候我们的自定义视图尺寸尝试去缩小到0。但是发现有约束冲突,由于优先级较低所以不再进行继续缩小。当self.viewHeader展开后,我们的自定义视图尝试去展开,展开后没有问题。
第二种办法: 在runLoop下一个循环中进行约束
在这里插入图片描述亲测这种办法也可以解决问题。在runLoop第一个循环周期内viweTemp的尺寸完成了从0展开。这时候和self.viewHeader没有关系。
在runLoop低二个循环周期时候完成约束。这时候其实父视图已经完成了布局的变化,视图已经完全的展开了,所以self.viewHeader也不会受到影响。
推荐:第一种方法
方法二要进行两次更新UI,如果由于计算错误,有可能第一次会看到一个不正确的UI。所以不推荐这种方法。
总结
当我们遇到控制台打印=="<NSLayoutConstraint:0x600001ac0140 xxxView:0x7ff534cca8a0.width == 0>"== 的问题。这时候UI界面却完好。
这时候我们要检查是不是用的tableView.tableHeaderView,如果是,那么就这样进行修改试试看吧。