天天看点

坑:iOS11开始Cell约束异常问题

背景:从iOS11开始,突然发现项目里面进入tableView相关页面都开始报约束异常的问题,异常内容提示约束高度和Cell的contentView高度不一致。然后通过UI调试发现确实不一致了,但是很奇怪的问题是在iOS10以前的系统上就没有问题。问题的具体症状是Cell使用了自适应高度,在xib中因为Cell有下滑线的原因ContentView比Cell高度小0.5,所以约束高度加起来比Cell小0.5,但是当程序运行起来,一看异常提示,ContentView的高度变了,比Cell高度小0.3333333,大概情况就是ContentView高度变成了xx.66666667,比原来正常的xx.5多了一些高度,这个十分奇怪,这也是约束异常的原因。

思考:当时遇到这个问题考虑了很久,第一感觉是iOS11出了名的Bug多,多半是个系统Bug。然后想办法处理这个问题的思路就是改变ContentView的高度就好了,想了很多办法尝试有些有效有些无效,但是基本上都不是很好的处理方式,也一直拖着没有去解决。最后发现最好的办法就是让tableView的分割线隐藏,然后手动绘制Cell分割线,然而依然不够优雅,但是有效简单。后来在整理项目代码的时候,发现了当时写的这个绘制Cell分割线的方法,看了下自己的代码很简单就是绘制一个0.5高度的线,然后突然想到了很久以前的一篇文章,关于如何绘制1像素的线条,原理很简单就是按屏幕实际分辨率进行绘制,为了保障清晰可见,应该计算好位置,防止位置在两个像素中间的地方这样会造成线条虚化。这时候脑洞一开,cell的分割线如果也是1像素的线,那么0.3333就是在3x屏幕下的高度,正好平时用的是plus的机型,而xib中选择的是4.7寸的屏幕,所以线条高度是0.5,但是运行时系统应该会把线条高度重新调整,但是Cell内容的约束是不会调整的。最后尝试了一下,把xib的机型换成plus的,一看分割线高度,果然变小了,ContenView高度xxx.666667。

总计:因为xib或者sb中考虑了机型的情况加上xib中分割线不能隐藏才造成了约束设置的时候只考虑到了某个屏幕,恰好又是用的另一种屏幕大小的模拟器的时候,就出现了约束比匹配的问题。这个问题卡了我很久,问了很多群和大神都没人知道,最后是被自己破解了。解决办法,只要用了IB来做页面就会出现这个问题,目前来说三个办法1)忽略这个问题不处理,2)设置Cell内容约束高度的和>=某个值,或者<=某个值,比如bottom约束>=8这样子,当ContentView高度变高,约束依然满足3)动态调整ContentView高度和分割线高度。就目前来看,如果不是特别在意这个问题,1和2是比较好的选择,xib用什么尺寸就用什么模拟器,当看不到,或者2,不过鉴于系统中众多的Cell,个人感觉如果有强迫症的话用runtime动态调整