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

应用重启后Navigation Bar标题被截断问题求助

导航栏标题重启后截断问题排查与解决

问题描述

通过Xcode运行应用时,Navigation Bar标题显示正常,但关闭应用后重新启动,标题文本会被截断并显示为“...”。尝试过相关解决方案但未解决。

相关代码实现

BaseViewController

import UIKit
import SnapKit

open class BaseViewController: UIViewController {
    public lazy var navigationShadowView: UIView = {
        let view = UIView()
        DispatchQueue.main.async {
            let gradientLayer = CAGradientLayer()
            gradientLayer.colors = [UIColor.Blue10.cgColor, UIColor.Blue0.withAlphaComponent(0.0).cgColor]
            gradientLayer.frame = view.bounds
            view.layer.addSublayer(gradientLayer)
        }
        return view
    }()

    public override func viewDidLoad() {
        loadDefaults()
        setupUI()
    }
}

extension BaseViewController {
    private func loadDefaults() {
        view.backgroundColor = .white

        tabBarController?.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
        navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

        // MARK: Navigation bar bottom shadow
        view.addSubview(navigationShadowView)
        navigationShadowView.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
            make.leading.equalTo(view.snp.leading)
            make.trailing.equalTo(view.snp.trailing)
            make.height.equalTo(10)
        }
    }

    @objc open func setupUI() {

    }
}

CustomerProjectListVC

import UIKit
import CoreModule
import SnapKit
import Combine

class CustomerProjectListVC: BaseViewController {
    lazy var refreshControl: UIRefreshControl = {
        let refresh = UIRefreshControl()
        refresh.addTarget(self, action: #selector(refreshProjects(_:)), for: .valueChanged)
        return refresh
    }()
    lazy var jobsTableView: UITableView = {
        let tableView = UITableView()
        tableView.showsHorizontalScrollIndicator = false
        tableView.showsVerticalScrollIndicator = false
        tableView.separatorStyle = .none
        tableView.rowHeight = 220
        tableView.backgroundColor = .Blue0

        tableView.addSubview(refreshControl)

        tableView.register(ProjectListTableViewCell.self, forCellReuseIdentifier: ProjectListTableViewCell.identifier)

        tableView.dataSource = self
        tableView.delegate = self
        return tableView
    }()

    private let viewModel = CustomerProjectListViewModel()
    private var subscription = Set<AnyCancellable>()

    override func viewDidAppear(_ animated: Bool) {
        tabBarController?.navigationItem.title = "Project List"
        tabBarController?.navigationItem.rightBarButtonItem = nil
    }

    override func setupUI() {
        view.addSubview(jobsTableView)
        jobsTableView.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
            make.leading.equalToSuperview()
            make.trailing.equalToSuperview()
            make.bottom.equalToSuperview()
        }

        populateData()
    }
}

CustomerTabBarController

class CustomerTabBarController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()

        tabBar.backgroundColor = .white

        viewControllers = [
            createNavController(for: sideMenuController(), title: "Home", image: UIImage(named: .TabBarHome)!),
            createNavController(for: ProfileVC(), title: "Profile", image: UIImage(named: .TabBarProfile)!),
            createNavController(for: NewPostVC(), title: "Post", image: UIImage(named: .TabBarPost)!),
            createNavController(for: CustomerProjectListVC(), title: "Chatbox", image: UIImage(named: .TabBarChatBox)!),
            createNavController(for: HomeVC(), title: "Notification", image: UIImage(named: .TabBarNotification)!)
        ]
    }
}

extension CustomerTabBarController {
    fileprivate func createNavController(for rootViewController: UIViewController,
                                         title: String,
                                         image: UIImage) -> UIViewController {
        rootViewController.tabBarItem.title = title
        rootViewController.tabBarItem.image = image
        return rootViewController
    }
}

extension CustomerTabBarController {
    private func configureSideMenu() {
        SideMenuController.preferences.basic.menuWidth = UIScreen.main.bounds.width - 80
        SideMenuController.preferences.basic.position = .above
        SideMenuController.preferences.basic.direction = .right
    }

    private func sideMenuController() -> SideMenuController {
        configureSideMenu()
        return SideMenuController(contentViewController: HomeVC(), menuViewController: SideMenuVC())
    }
}

应用初始化代码

let viewController = CustomerTabBarController()
let navigationViewController = UINavigationController(rootViewController: viewController)
window?.rootViewController = navigationViewController
window?.makeKeyAndVisible()

问题原因分析

核心问题在于直接修改tabBarController?.navigationItem.title,而你的层级结构是UINavigationController -> CustomerTabBarController -> 子VC,外层导航栏会复用tabBarController的navigationItem,但应用重启后,系统布局计算时机更严格,直接修改父容器的导航属性会导致布局状态不一致,无法正确计算标题宽度。Xcode调试环境下系统有额外布局校验逻辑,所以暂时掩盖了问题。

解决方案

1. 改为设置当前VC的navigationItem标题

修改CustomerProjectListVC的viewDidAppear方法,直接操作当前VC的导航属性,而非tabBarController的:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationItem.title = "Project List"
    navigationItem.rightBarButtonItem = nil
}

2. 修正backBarButtonItem的设置逻辑

在BaseViewController的loadDefaults中,删除对tabBarController?.navigationItem的修改,只设置当前VC的返回按钮:

private func loadDefaults() {
    view.backgroundColor = .white

    // 仅设置当前VC的返回按钮文本
    navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

    // MARK: Navigation bar bottom shadow
    view.addSubview(navigationShadowView)
    navigationShadowView.snp.makeConstraints { make in
        make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
        make.leading.equalTo(view.snp.leading)
        make.trailing.equalTo(view.snp.trailing)
        make.height.equalTo(10)
    }
}

3. 强制导航栏重新布局(可选)

如果上述方法无效,可在设置标题后强制触发导航栏布局更新:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationItem.title = "Project List"
    navigationItem.rightBarButtonItem = nil
    navigationController?.navigationBar.setNeedsLayout()
    navigationController?.navigationBar.layoutIfNeeded()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 10:45:37