嵌套UITabBarController层级重叠:二级TabBar被遮挡如何解决?
Hey there! I totally get how frustrating it is when your nested tab bars end up overlapping—been there, done that. Let's break down why this happens and how to fix it properly.
Why the Overlap Happens
By default, every UITabBarController automatically adjusts its child view controllers' frames to sit above its own tab bar. When you nest a second tab bar controller inside the first one, the outer (primary) tab bar sits at the very bottom of the screen, and the inner (secondary) tab bar controller doesn't account for that extra bottom space—so its tab bar gets pushed under the primary one.
Solution 1: Adjust Frames Manually
You can tweak the frame of your secondary tab bar controller's view and tab bar to make room for the primary tab bar. Add this code to your secondary UITabBarController subclass:
override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() // Grab the height of the parent tab bar guard let parentTabBarHeight = (parent as? UITabBarController)?.tabBar.frame.height else { return } // Shrink the current view's height to make space for the parent tab bar self.view.frame = CGRect( x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height - parentTabBarHeight ) // Reposition the secondary tab bar to sit just above the parent tab bar self.tabBar.frame = CGRect( x: 0, y: self.view.frame.height - self.tabBar.frame.height, width: self.tabBar.frame.width, height: self.tabBar.frame.height ) }
Solution 2: Use Auto Layout (More Reliable)
For a cleaner, auto-layout friendly approach, constrain the secondary tab bar controller's view to the top of the primary tab bar. Add this to your secondary UITabBarController subclass:
override func viewDidLoad() { super.viewDidLoad() guard let parentTabBar = (parent as? UITabBarController)?.tabBar else { return } // Disable auto-resizing mask so we can use custom constraints self.view.translatesAutoresizingMaskIntoConstraints = false // Pin the view to the superview's edges, except the bottom which pins to the parent tab bar's top NSLayoutConstraint.activate([ self.view.topAnchor.constraint(equalTo: self.view.superview!.topAnchor), self.view.leadingAnchor.constraint(equalTo: self.view.superview!.leadingAnchor), self.view.trailingAnchor.constraint(equalTo: self.view.superview!.trailingAnchor), self.view.bottomAnchor.constraint(equalTo: parentTabBar.topAnchor) ]) // Prevent the view from extending under the parent tab bar self.edgesForExtendedLayout = [] }
Quick Storyboard Tweak (Optional)
If you prefer working in Interface Builder, select your secondary UITabBarController, go to the Attributes Inspector, and uncheck "Under Bottom Bars" under the Extend Edges section. This combined with the auto-layout code above will ensure no overlap.
Your Scenario Context
From your provided materials:
- Problem screenshot:
- Target effect:
- Your storyboard and source code confirm you've set up the nested structure correctly (embedding a tab bar controller inside another via
Editor -> Embed In -> Tab Bar Controller) - Your reproduction steps are spot-on for triggering this issue
A quick heads-up: Apple doesn't officially recommend nested tab bar controllers since it can go against human interface guidelines, but if your app's use case requires this structure, the solutions above will get you sorted.
内容的提问来源于stack exchange,提问作者Andre

