应用重启后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
相关产品推荐
相关产品推荐

