将子 UIViewConroller 添加到 UITabBarController
Posted
技术标签:
【中文标题】将子 UIViewConroller 添加到 UITabBarController【英文标题】:add child UIViewConroller to UITabBarController 【发布时间】:2018-11-16 12:51:27 【问题描述】:我的应用程序的结构如下:
UITabBarController -> UINavigationController -> [UIViewController1, UIViewController2, UIViewController3]
我需要实现的是在一个小框架中的 tabBar 上方显示和隐藏一个子 UIViewController,因此它在导航堆栈中的所有控制器上都是可见的。因此,当用户在堆栈中来回导航时,如果添加了该子级,它必须在所有控制器中可见。
我已尝试将子项添加到 UITabBarController 并且它工作正常,我得到的问题是阴影选项卡项被添加到选项卡栏,这是我不想要的。
我已经尝试将孩子添加到导航控制器,但是当导航回堆栈时会增加其他问题,它会关闭孩子而不是自我并加载相同的控制器。
有没有人建议如何在整个导航过程中保留这个子控制器。
我在这里搜索过任何建议,但没有一个与我的情况一样,所以没有帮助。
谢谢
【问题讨论】:
你想要 UIViewContrller1,2,3... 在孩子可见时调整大小吗? 不,我不需要调整控制器的大小。 【参考方案1】:我假设您以编程方式将容器视图添加到标签栏控制器中,然后将子视图控制器添加到该容器视图中。我说的对吗?
如果是这种情况,标签栏控制器会将子控制器添加到其viewControllers
数组中。
您可以在添加孩子后立即致电viewControllers?.removeLast()
解决此问题。
这段代码对我有用:
override func viewDidLoad()
super.viewDidLoad()
let containerView = UIView()
view.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.bottomAnchor.constraint(equalTo: tabBar.topAnchor).isActive = true
containerView.leftAnchor.constraint(equalTo: tabBar.leftAnchor, constant: 40).isActive = true
containerView.rightAnchor.constraint(equalTo: tabBar.rightAnchor, constant: -40).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 150).isActive = true
if let childVC = self.storyboard?.instantiateViewController(withIdentifier: "ChildViewController")
addChild(childVC)
containerView.addSubview(childVC.view)
childVC.didMove(toParent: self)
childVC.view.translatesAutoresizingMaskIntoConstraints = false
childVC.view.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
childVC.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
childVC.view.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
childVC.view.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
if let childIndex = viewControllers?.firstIndex(of: childVC)
viewControllers?.remove(at: childIndex)
在这里,我不只是调用removeLast()
,而是检查了childVC
是否真的在那个数组中。只是为了更安全。
【讨论】:
我会尝试并告诉你进展如何 好吧,我遇到了同样的问题并尝试了你的解决方案:它正在工作,但我认为不添加视图控制器作为子视图控制器没有区别......我刚刚检查了调试视图层次结构和视图控制器未显示。而且,子视图控制器没有父视图,也没有调用它的生命周期方法。【参考方案2】:问题:
将子视图控制器添加到UITablViewConltroller
会向标签栏添加一个新标签。这在 ios 13.4 中很明显
解决方案
解决方案是覆盖 viewControllers
并仅返回原始控制器。
/// Neglect child insertion to `viewControllers`
var _viewControllers: [UIViewController]?
override var viewControllers: [UIViewController]?
get
return _viewControllers
set
_viewControllers = newValue
还有更多
更改标签栏项目徽章
//This would not work any more
//viewControllers?.last?.tabBarItem.badgeValue = badgeValue
//Use this way instead
tabBar.items?.last?.badgeValue = badgeValue
【讨论】:
【参考方案3】:最新:
过滤掉 viewControllers
属性实际上不起作用(请参阅下面的“旧答案”),我们在某个时候再次使用该解决方案解决了问题。
我们当时所做的是将UITabBarController
嵌入到UIViewController
中,然后将我们想要的视图添加到视图控制器中。布局设置为嵌入式标签栏控制器的标签栏添加约束。它现在似乎可以正常工作了。
PD:您可能希望覆盖 UIViewController
的所有 childFor...
方法,以便状态栏样式、主页指示器等与普通 UITabBarController
一样工作。
旧答案:
不幸的是,没有一个提议的解决方案对我有用,但我只是通过从 UITabBarController 的 viewControllers
getter 中过滤掉孩子来实现它:
override var viewControllers: [UIViewController]?
get
super.viewControllers?.filter viewController in
viewController != self.yourChildViewController
set
super.viewControllers = newValue
【讨论】:
以上是关于将子 UIViewConroller 添加到 UITabBarController的主要内容,如果未能解决你的问题,请参考以下文章
如何在将数据加载到 UIViewConroller Swift 时创建正在加载的 UIView