日常开发中,大家可能会通过修改约束的 priority
来到达布局的目的。但是,如果使用不当,便会遇到崩溃问题。
首先,看下说明文档如下:
/* If a constraint's priority level is less than UILayoutPriorityRequired, then it is optional. Higher priority constraints are met before lower priority constraints.
Constraint satisfaction is not all or nothing. If a constraint 'a == b' is optional, that means we will attempt to minimize 'abs(a-b)'.
This property may only be modified as part of initial set up or when optional. After a constraint has been added to a view, an exception will be thrown if the priority is changed from/to NSLayoutPriorityRequired.
*/
@property UILayoutPriority priority;
总结下文档中的几点:
- 如果该值小于
UILayoutPriorityRequired
,那么这个约束就是可选的。 - 值高的比值低的优先。
- 约束并不是总是尽如人意的,如果一个
a == b
的优先值是可选的,结果可能是取abs(a-b)
。 - 这个属性在两种条件下可以修改
- 初始化时候
- 可选约束条件下
如果一个约束已经加到了 view
对象上,在两种情况下修改该属性值会抛出异常
- 将该值改为
NSLayoutPriorityRequired
- 该值本来为
NSLayoutPriorityRequired
,修改为其他值
注意,上面第 4 点就是我遇到的问题,在 tableView
这种复用 cell
的视图中,就会出现修改该值频繁的情况。由于通常情况下创建的约束该属性一般都是 NSLayoutPriorityRequired
, 所以,我们需要修改成低级别的来实现自己的需求。
后续补充
根据上面第四点,UILayoutPriorityRequired
只能在初始化条件下可以修改,那么什么情况下算是初始化呢?就是在布局更新之前,也就是layoutSubviews
调用之前。所以,对于cell
这种复用的视图,很容易会复现崩溃。那么对于 UIView
这类基本视图,会发生崩溃吗?
当然也是可以的,当某种情况下需要进行强制更新约束时,便会调用layoutIfNeeded
,触发 layoutSubviews
方法导致约束更新,后续在进行UILayoutPriorityRequired
的修改,便会崩溃。但是这种情况,iOS 13 不会崩溃,iOS 13 以下(iOS 12 已经测过)才会崩溃。
现在,一般开发都是基于 iOS 13,并且肯定会适配 iOS 12,所以为了避免上述情况还是要注意,如果后续需要修改priority
,不要使用UILayoutPriorityRequired
。
就算自己可以保证不调用layoutIfNeeded
, 禁不住别人不调用呀。不然后续出了问题,还不是自找麻烦。当然,这也体现出代码的健壮性。代码易懂是一方面,别人修改不会影响也是一方面。