控制台输出约束警报,界面完好

1,838 阅读3分钟

现象

在这里插入图片描述
发现在使用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,如果是,那么就这样进行修改试试看吧。