Swift设备旋转时更新programmatic约束出现冲突该如何解决?
冲突原因
你每次调用comicImage.widthAnchor.constraint(equalToConstant:)都会生成全新的宽度约束,旧约束没有被移除就激活新约束,多个同优先级的宽度约束同时生效,必然触发系统冲突警告。而且viewDidLayoutSubviews会被频繁触发,你每次调用都新增约束,冲突会越来越多。
最优实现方案
不需要每次删除重建约束,直接持有宽度约束的引用,修改constant属性即可(这是NSLayoutConstraint唯一支持动态修改的属性,性能最优)。
步骤1:声明约束属性
在你的ViewController中新增属性存储宽度约束:
private var comicImageWidthConstraint: NSLayoutConstraint?
步骤2:修改初始化约束逻辑
原来的初始化代码不要直接激活新生成的约束,先赋值给声明的属性再激活:
view.addSubview(comicImage) comicImage.translatesAutoresizingMaskIntoConstraints = false comicImageWidthConstraint = comicImage.widthAnchor.constraint(equalToConstant: 200.0) comicImageWidthConstraint?.isActive = true
步骤3:修改方向切换逻辑
不需要新增约束,直接修改约束的constant值后触发布局更新即可:
private func changeOrientation() { let isLandscape = UIScreen.main.bounds.width > UIScreen.main.bounds.height print(isLandscape ? "landscape" : "portrait") comicImageWidthConstraint?.constant = isLandscape ? 400.0 : 200.0 view.layoutIfNeeded() }
额外优化建议
viewDidLayoutSubviews触发频率极高,哪怕只是界面上其他元素微小变动都会触发,不需要每次都执行方向判断逻辑。你可以换成监听尺寸类变化的回调,只在横竖屏真的切换时才更新:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) guard previousTraitCollection?.horizontalSizeClass != traitCollection.horizontalSizeClass else { return } changeOrientation() }
内容的提问来源于stack exchange,提问作者dreadbot
相关产品推荐
相关产品推荐

