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

Swift自定义UINavigationBar加载时出现约束冲突问题求助

解决自定义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并设置约束,这样能彻底避免系统自动生成的约束冲突:

  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:39:03