Navigation title is not visible in root of navigation stack of UITabBarController using UITab layout on iPad

Description

Title of the view controller is not displayed for the 1st view controller in navigation stack.

Is there a way to show it?

Main problem is that selected tab is a UITabGroup and there's no way to understand which child of it is currently selected without opening the sidebar or guessing by the content.

Human Interface Guidelines

In the guidelines there are examples with title visible on the iPad in similar case: https://developer.apple.com/design/human-interface-guidelines/tab-bars

Code

import UIKit
import SwiftUI

struct TestView: View {
    var tab: UITab?
    let id = UUID()

    var body: some View {
        ScrollView {
            HStack {
                Spacer()
                VStack {
                    Text(tab?.title ?? id.uuidString)
                }
                Spacer()
            }
            .frame(height: 1000)
            .background(.red)
            .onTapGesture {
                tab?.viewController?.navigationController?.pushViewController(
                    TestViewController(nil), animated: true
                )
            }
        }
    }
}

class TestViewController: UIHostingController<TestView> {
    let _tab: UITab?

    init(_ tab: UITab?) {
        self._tab = tab
        super.init(rootView: TestView(tab: _tab))
    }
    
    @MainActor @preconcurrency required dynamic init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = _tab?.title ?? "tab-nil"
    }
}

class ViewController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()

        mode = .tabSidebar

        let provider: (UITab) -> UIViewController = { tab in
            print(tab)
            return TestViewController(tab)
        }

        let tab1 = UITabGroup(
            title: "Tab 1",
            image: UIImage(systemName: "1.square.fill"),
            identifier: "tab1",
            children: [
                UITab(title: "Sub 1",
                      image: UIImage(systemName: "1.circle"),
                      identifier: "First Tab",
                      viewControllerProvider: provider),
                UITab(title: "Sub 2",
                      image: UIImage(systemName: "2.circle"),
                      identifier: "Second Tab",
                      viewControllerProvider: provider)
            ])
        tab1.selectedChild = tab1.children[0]
        tab1.managingNavigationController = UINavigationController()

        let tab2 = UITabGroup(
            title: "Tab 2",
            image: UIImage(systemName: "2.square.fill"),
            identifier: "Section one",
            children:
                [
                    UITab(
                        title: "Sub 1",
                        image: UIImage(systemName: "a.circle"),
                        identifier: "Section 1, item A",
                        viewControllerProvider: provider),

                    UITabGroup(title: "Sub Group", image: nil, identifier: "q",
                               children: [
                                UITab(
                                    title: "Item 1",
                                    image: UIImage(systemName: "b.circle"),
                                    identifier: "c1",
                                    viewControllerProvider: provider),
                                UITab(
                                    title: "Item 2",
                                    image: UIImage(systemName: "b.circle"),
                                    identifier: "c2",
                                    viewControllerProvider: provider)
                               ],
                               viewControllerProvider: provider
                              ),
                ]
        )
        tab2.selectedChild = tab2.children[0]
        tab2.managingNavigationController = UINavigationController()

        tabs = [
            tab1,
            tab2,
        ]

        selectedTab = tab1
    }
}

The navigation title shown in the iPad examples you linked appear to have a Navigation Title Display Mode of type Large Title, which is not configured to display by default.

In UIKit, a large title can be configured using largeTitleDisplayMode with prefersLargeTitles.

 Travis Trotto - DTS Engineer

Thank you, large title appears!

But if the view is scrolled there's no regular title for the root view controller.

This is the root view controller when scrolled (has no title, can't understand which subtab is selected in the UITabGroup)

This is the 2nd view controller when scrolled (which has the title and looks like expected)

Is it be possible to have a title on the root view controller like on the 2nd view controller?

Hello mkavaleuski,

No title on the root item is expected for the case where titleMenuProvider == nil. For the case where it is non-nil, the title would be shown normally. Please see titleMenuProvider for how to add one.

Thank you for your patience,

Richard Yeh  Developer Technical Support

Navigation title is not visible in root of navigation stack of UITabBarController using UITab layout on iPad
 
 
Q