Search code examples
iosuikituinavigationbarswift5uinavigationitem

Navigation bar title truncated after relaunching application


Recently I getting e wired problem

When I run my application from XCode navigation title text is showing perfect. But when I close the application and reluanch again text cuts off with

...

I tried the following questions but no luck.

Here is my 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() {

    }
}

I populate the view in viewcontroller like below

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()
    }
}

Here is the CustomeTabBarController

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())
    }
}

And I am initiating the viewcontroller like following

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

Navigation Bar Shrinking after relaunching app

Navigation Bar Title truncated

Here I attached some screenshots.

Following one is launching from XCode

https://pasteboard.co/HHl1vFJYbzeX.png

2nd one is after relaunch

https://pasteboard.co/kw3zRZqic9q7.png

My question is why this does not happen when runs from XCode but when the app relaunchs. I have tried many ways like setupui from viewdidappear methods and others. But no luck. Please help me out.


Solution

  • It seems like you're setting the title of a wrong view controller and it's also worth checking if you have the correct navigation hierarchy. My best be would that this is causing the problems.

    The typical hierarchy of tab-based apps is the following: UITabBarController (root) → UINavigationController (one per each tab) → YourViewController.

    Now, I see that you're setting the navigation title as follows:

    tabBarController?.navigationItem.title = "Project List"
    

    This is strange and unusual. The view controller is supposed to set its own title like this:

    navigationItem.title = "Project List"
    

    Then its parent UINavigationController will be able use this title. It's also worth setting the title in viewDidLoad, not it viewDidAppear so that the title is visible before the transition animation and not after it.

    So check the hierarchy of the view controllers in the app and make sure each view controller only sets its own navigation title.

    If that doesn't help, I'll be happy to retract my answer to avoid confusion.