Swift自定义UINavigationBar加载时出现约束冲突问题求助
我来帮你搞定这个约束冲突的问题!从控制台的错误信息来看,问题出在系统为导航栏标题自动添加的两个约束上:标题Label的firstBaseline和标题容器的top +23约束,以及top >= 标题容器top的约束,这两个约束因为你的自定义设置(导航栏高度、标题字体大小、垂直偏移)互相冲突了。
问题根源
你直接修改了导航栏的frame.height,又设置了标题的垂直偏移setTitleVerticalPositionAdjustment(-5, for: .default),再加上30号的大字体,导致系统自动生成的标题布局约束出现矛盾——系统既要保证标题的基线位置,又要满足顶部间距要求,最终触发了冲突。
解决方案
下面给你两种可行的解决办法,推荐第二种更稳妥的方案:
方案1:规范自定义导航栏高度,调整垂直偏移
不要直接修改frame.size.height,而是通过重写sizeThatFits来定义导航栏高度,同时调整标题的垂直偏移值,避免约束冲突:
class CustomNavBar: UINavigationBar { // 重写sizeThatFits来设置自定义高度 override func sizeThatFits(_ size: CGSize) -> CGSize { var fittingSize = super.sizeThatFits(size) fittingSize.height = 60 // 你的目标高度 return fittingSize } override init(frame: CGRect) { super.init(frame: frame) setupNavBar() } required init?(coder: NSCoder) { super.init(coder: coder) setupNavBar() } private func setupNavBar() { backgroundColor = appColour tintColor = .white titleTextAttributes = [ NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont(name: "Avenir-Heavy", size: 30)! ] // 调整偏移值,避免和系统约束冲突,比如改成-2或者直接移除这行 setTitleVerticalPositionAdjustment(-2, for: .default) } }
方案2:自定义TitleView(推荐)
完全抛弃系统的title,自己创建标题Label并设置约束,这样能彻底避免系统自动生成的约束冲突:
- 修改ViewController的
viewDidLoad方法:
override func viewDidLoad() { super.viewDidLoad() // 创建自定义标题Label let titleLabel = UILabel() titleLabel.text = "Configure" titleLabel.font = UIFont(name: "Avenir-Heavy", size: 30)! titleLabel.textColor = .white navigationItem.titleView = titleLabel // 添加约束精确控制标题位置 titleLabel.translatesAutoresizingMaskIntoConstraints = false guard let navBar = navigationController?.navigationBar else { return } NSLayoutConstraint.activate([ titleLabel.centerYAnchor.constraint(equalTo: navBar.centerYAnchor, constant: -5), // 这里的-5就是你想要的垂直偏移 titleLabel.centerXAnchor.constraint(equalTo: navBar.centerXAnchor) ]) // 保留你的按钮设置 navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(start)) navigationItem.rightBarButtonItem!.imageInsets = UIEdgeInsets(top: -7, left: 0, bottom: 0, right: 0) navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "Folder")!, style: .plain, target: self, action: #selector(viewSaved)) navigationItem.leftBarButtonItem!.imageInsets = UIEdgeInsets(top: -7, left: 0, bottom: 0, right: 0) }
额外提醒
iOS 11及以后的导航栏完全基于Auto Layout布局,直接修改frame会破坏系统的布局逻辑,这也是导致约束冲突的重要原因。所以自定义导航栏高度时,优先使用重写sizeThatFits的方式。
内容的提问来源于stack exchange,提问作者Jack Whitaker
相关产品推荐
相关产品推荐

