将子视图控制器添加到UITabBarController

8
我的应用程序结构如下:
UITabBarController -> UINavigationController -> [UIViewController1,UIViewController2,UIViewController3]
我需要实现的是在小框架中显示和隐藏一个子UIViewController,使其可见于导航堆栈中的所有控制器之上。因此,当用户在堆栈中前进和后退时,如果添加了该子项,则必须在所有控制器之上可见。
我尝试将子项添加到UITabBarController中,这很好用,但问题是tabbar会添加一个阴影标签项,而我不想要它。
我还尝试将子项添加到导航控制器中,但在堆栈中返回时会出现其他问题,它会关闭该子项并加载相同的控制器。
是否有人有关于如何在整个导航过程中保留此子控制器的建议?
我在这里搜索了任何建议,但都没有像我的情况那样,所以没有帮助。
谢谢

当子视图可见时,您是否希望调整UIViewController1、2、3等大小? - Yevgeniy Leychenko
不需要调整控制器的大小。 - Stan
3个回答

7

我猜你是通过编程方式将容器视图添加到了选项卡控制器中,然后将子视图控制器添加到该容器视图中。我的理解正确吗?

如果是这种情况,选项卡控制器会将子控制器添加到其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是否实际上在该数组中。这样做是为了更加安全。


我会尝试并告诉您进展如何。 - Stan
我遇到了相同的问题并尝试了您提供的解决方案:它确实有效,但我没有看到将视图控制器添加为子视图控制器时有任何区别... 我只是使用Debug View Hierarchy进行了检查,但是该视图控制器未显示。此外,子视图控制器没有父级并且其生命周期方法也没有被调用。 - vmeyer

1

问题:

将子视图控制器添加到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

1

最新消息:

过滤掉viewControllers属性实际上并没有起作用(请参见下面的“旧答案”),我们在某个时候再次遇到了这个问题。

然后我们将UITabBarController嵌入到一个UIViewController中,然后将我们想要的视图添加到该视图控制器中。布局是通过向嵌入式标签栏控制器的标签栏添加约束来设置的。现在似乎没有任何问题。

附注:您可能需要覆盖所有UIViewControllerchildFor...方法,以便状态栏样式、主指示器等能像普通的UITabBarController一样工作。

旧答案:

对我来说,没有提出的解决方案可行,但我通过仅从UITabBarController的viewControllers getter中过滤掉子项来使其工作:

override var viewControllers: [UIViewController]? {
    get {
        super.viewControllers?.filter { viewController in
            viewController != self.yourChildViewController
        }
    }
    set {
        super.viewControllers = newValue
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接