You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS中NSLayoutConstraint优先级能否在required与非required间修改

NSLayoutConstraint 优先级修改相关提问

正如NSLayoutConstraint优先级相关的官方文档中所述:

优先级不得在非required与required之间相互切换。

但我实际尝试该操作时却成功生效,示例代码如下:

var centerConstraint: UILayoutConstraint!
var topConstraint: UILayoutConstraint!

signInButton = UIButton(type: .system)
// Some setting code
...

signUpView = UIView()
// Some setting code
...

signInView.addSubview(signInButton)

centerConstraint = signInButton.centerXAnchor.constraint(equalTo: signInView.centerXAnchor)
centerConstraint.isActive = true
    
topConstraint = signInButton.centerXAnchor.constraint(equalTo: signInView.leadingAnchor)
topConstraint.priority = .defaultHigh
topConstraint.isActive = true

我创建了signInButton与signInView,其中signInButton有两个约束:一个使用默认的.required优先级,另一个优先级为.defaultHigh。

后续当用户点击按钮时,我会修改centerConstraint的优先级为:

centerConstraint.priority = .defaultLow

该操作在iOS 13与iOS 14模拟器中均可正常运行,与文档描述不符:

若在约束被添加到视图后,将iOS的UILayoutPriorityRequired(macOS中为required优先级)修改为更低优先级,或将低优先级修改为required优先级,系统应抛出异常。

我想知道是否是官方文档内容已过期?目前是否允许在required与非required之间修改NSLayoutConstraint的优先级?


问题解答

文档描述的规则在iOS 12及更早版本是强制生效的——只要对已激活的约束跨required/非required档位修改优先级,系统会直接触发断言崩溃。
从iOS 13开始,Apple 悄悄移除了这个硬校验,不会再对这类操作抛异常,也不拦截修改,这就是你在iOS 13、14模拟器上运行不报错的根本原因。

文档没有过期,只是没同步系统行为的变更,而且至今仍然不推荐这种操作,原因很实际:

  • Auto Layout的约束求解器的设计逻辑里,required(优先级值1000)的约束属于“必须无条件满足”的不可变集合,一旦在约束激活后修改这部分的优先级,会直接打破求解器的预期状态。
  • 你现在没出问题,只是因为当前的约束组合刚好没有硬冲突:把原来required的居中约束改成.defaultLow,和已有的.defaultHigh的贴边对齐约束共存时,高优先级约束自然生效,低优先级约束被忽略,整个求解过程是自洽的。
  • 如果反过来操作——把一个已激活的非required约束直接改成required,而当前视图层级已经存在同方向的required约束,求解器不会崩溃,但会随机打破其中一个约束的布局,还不会输出清晰的冲突日志,这类问题排查成本极高。

另外你代码里有个笔误:UIKit里根本没有UILayoutConstraint这个类型,正确类型是NSLayoutConstraint,只是因为你用了隐式解包可选,编译器没在声明阶段报错而已。

工程上的通用正确做法是:提前声明好两套需要切换的约束,通过修改isActive属性来切换布局,不要在运行时跨required档位修改已激活约束的优先级。


内容的提问来源于stack exchange,提问作者migrant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.29 09:06:05