I'm using UIKit, and currently this is my workaround to make the tab bar to revert it back to the old look (displayed at the bottom).
class CustomTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
guard #available(iOS 18, *), UIApplication.shared.isPad else {
return
}
traitOverrides.horizontalSizeClass = .compact
}
}
class CustomTabBarChildNavigationController: UINavigationController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
adjustSizeClass()
}
}
class CustomTabBarChildViewController: UIViewController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
adjustSizeClass()
}
}
extension UIViewController {
var rootViewControllerHorizontalSizeClass: UIUserInterfaceSizeClass {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let keyWindow = windowScene.windows.first(where: { $0.isKeyWindow }),
let rootViewController = keyWindow.rootViewController else {
return .regular
}
return rootViewController.traitCollection.horizontalSizeClass
}
func adjustSizeClass() {
guard #available(iOS 18, *), UIApplication.shared.isPad else {
return
}
// The child view controllers of the tab bar should follow the horizontal size class of the
// root view controller else it will have the side effect, e.g. the child view controller
// will show the content using compact horizontal size class.
traitOverrides.horizontalSizeClass = rootViewControllerHorizontalSizeClass
}
}
Now, change your existing subclasses to inherit the new class:
UITabBarController
-> CustomTabBarController
UINavigationController
-> CustomTabBarChildNavigationController
UIViewController
-> CustomTabBarChildViewController
It works fine for my app so far. This workaround also covers the scenarios of split view and multitasking.
If you find any issue with this approach, please share it here.