如何在现有UITabBarController中嵌入带持久UIView的新ViewController?
我完全理解你的需求——切换TabBar标签时,希望有一个UIView能稳定保持显示不消失,而且不想重新创建已有的UITabBarController。其实不用把承载UIView的ViewController嵌入现有TabBar,反过来操作更合理:把现有TabBarController作为父ViewController的子控制器,让持久UIView留在父VC的视图层级里即可。下面是具体的Interface Builder操作步骤:
步骤1:准备基础视图控制器
打开你的Storyboard,找到已经创建好的UITabBarController,以及你打算放置持久UIView的ViewController(下文称它为「父VC」)。如果父VC还不是初始控制器,先选中它,在右侧Attributes Inspector里勾选「Is Initial View Controller」,把它设为Storyboard的根控制器。
步骤2:添加并布局持久UIView
在父VC的视图画布上,拖入你需要持久显示的UIView,调整好它的位置和尺寸(比如固定在顶部、底部或者屏幕某个固定区域),给它设置好自动布局约束,确保在不同屏幕尺寸下都能保持正确位置。
步骤3:关联现有TabBarController到父VC
这里不要用系统的「Embed In Tab Bar Controller」选项(它会新建TabBar实例),我们用Container View来关联已有的TabBar:
- 拖一个Container View到父VC的视图里,调整它的frame,让它避开刚才添加的持久UIView(比如持久UIView在顶部,Container View就占据剩下的屏幕区域)。
- 选中这个Container View,打开右侧的Connections Inspector(插头图标),找到「viewController」这个出口,按住鼠标左键拖到你的现有UITabBarController上,松开后就完成了两者的关联。
步骤4:优化布局(可选)
如果在IB里已经给Container View设置了正确的自动布局约束(比如和持久UIView的底部、父视图的左右边缘、底部对齐),这一步可以跳过。如果需要更精准的控制,也可以在父VC的代码里补充约束:
import UIKit class ParentViewController: UIViewController { @IBOutlet weak var persistentView: UIView! @IBOutlet weak var containerView: UIView! override func viewDidLoad() { super.viewDidLoad() guard let tabBarVC = children.first as? UITabBarController else { return } // 禁用自动调整mask,改用自动布局 tabBarVC.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tabBarVC.view.topAnchor.constraint(equalTo: persistentView.bottomAnchor), tabBarVC.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), tabBarVC.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), tabBarVC.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) } }
原理说明
这样操作后,父VC是整个界面的根控制器,它的视图不会因为TabBar标签切换而被销毁。持久UIView属于父VC的视图层级,而UITabBarController只是父VC的一个子控制器——切换标签时只是TabBar内部的子ViewController在切换,父VC的视图(包括那个持久UIView)会一直保持显示状态。
内容的提问来源于stack exchange,提问作者moosgrn

