I got around this without using the UITabBarController , instead creating a CustomTabBarController that inherits from the UIViewController . The user controller has a UITabBar at the bottom of its view and several other UIViewController built into Container Views. The user controller sets the isHidden property to true for the entire built-in view controller, except for the one that corresponds to the selected tab.
Below is a simple example with two tabs identified by their tag:
class CustomTabBarController: UIViewController, UITabBarDelegate { @IBOutlet weak var tab1View: UIView! @IBOutlet weak var tab2View: UIView! @IBOutlet weak var tabBar: UITabBar! override func viewDidLoad() { tabBar.delegate = self } func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { tab1View.isHidden = item.tag != 1 tab2View.isHidden = item.tag != 2 } }
This custom controller must be installed in the root of the UINavigationController , which itself must be installed as the main controller of the Split View controller:

This setting works for both iPad and iPhone:


There are several drawbacks to this method:
The user controller of the tab is less simple to work with - adding a new tab requires adding another built-in view and connecting it to the outlet in the controller.
Setting the title of the navigation element and panel elements on the left and right should be performed within the customizable controller of the tab bar when selecting a tab.
This method uses (I think) more memory than a regular UITabBarController , since all child view controllers load as soon as the application loads, and not when they are first displayed.
This setting will cause the tab bar to be hidden when displaying details in iPhone (portrait) mode. This was what I wanted, as well as the behavior in the Facebook Messenger app, but if you want the tab bar to be constantly visible, this method will not do it.
Andrew Bennet
source share