UIView嵌入UIViewController后退出全屏时Auto Layout失效问题
问题原因及修复方案
核心原因1:约束切换顺序错误,产生瞬时约束冲突
shortController方法中先激活小窗约束、再停用全屏约束的写法,会导致同一时间存在两个互相冲突的同层级约束,系统会随机中断其中一个约束解决冲突。未嵌入子VC时约束数量少尚能正常运行,嵌入子VC后约束复杂度提升,大概率会中断你需要激活的小窗约束,导致退出全屏后布局异常。
对应修复代码:
@objc func shortController() { // 先停用所有全屏约束 mainControllerLayout_top?.isActive = false mainControllerLayout_left?.isActive = false mainControllerLayout_bottom?.isActive = false // 再启用小窗约束 mainControllerLayout_top_short?.isActive = true mainControllerLayout_left_short?.isActive = true mainControllerLayout_bottom_short?.isActive = true mainControllerLayout_right?.isActive = true UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseInOut, animations: { mainControllerView.backgroundColor = UIColor(white: 0, alpha: 0.5) mainControllerView.layer.cornerRadius = 25 // 同时触发容器视图和根视图的布局更新,fullController方法的动画块也可同步添加该调用,保证逻辑一致 mainControllerView.layoutIfNeeded() self.view.layoutIfNeeded() }) }
核心原因2:子VC嵌入顺序不规范
当前子VC嵌入顺序不符合UIKit规范,可能导致子VC生命周期方法调用异常,进而触发子VC内部的异常布局更新,覆盖父容器的约束效果。
对应修复后的嵌入方法:
func embed(_ viewController: UIViewController, inView view: UIView) { // 正确顺序:先添加子控制器,再添加视图、配置约束 addChild(viewController) viewController.view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(viewController.view) NSLayoutConstraint.activate([ viewController.view.topAnchor.constraint(equalTo: view.topAnchor), viewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), viewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), viewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor) ]) viewController.didMove(toParent: self) }
可选优化建议
如果修复后仍有问题,可做如下检查:
- 打开Xcode控制台约束警告,确认子VC内部是否存在和父容器冲突的约束,可将子VC内部约束的优先级调低至
.defaultHigh(750),低于父容器约束的默认优先级.required(1000) - 检查子VC的
viewWillLayoutSubviews/viewDidLayoutSubviews方法中是否有修改视图frame的代码,避免覆盖Auto Layout效果
内容的提问来源于stack exchange,提问作者Travgalax
相关产品推荐
相关产品推荐

