Search code examples
iosuiviewcontrolleruitabbar

add child UIViewConroller to UITabBarController


the structure of my app is following:

UITabBarController -> UINavigationController -> [UIViewController1, UIViewController2, UIViewController3]

What I need to achieve is showing and hiding a child UIViewController just above the tabBar in a small frame, so it is visible over all the controllers in the navigation stack. So when user navigates back and forth the stack, if that child is added it has to be visible over all controllers.

I have tried adding the child to the UITabBarController and it is working fine, the problem I get is that a shadow tabbar item is added to the tabbar, which I do not want.

I have tried adding the child to the navigation controller but that adds other problems when navigating back in the stack, it dismisses the child instead of self and loads the same controller.

Does anyone have a suggestion on how to keep this child controller throughout the whole navigation process.

I have searched for any suggestions here, but none was like my case, so not helpful.

Thank you


Solution

  • I assume you added container view programmatically into you tabbar controller, then you added child view controller into that container view. Am I right?

    If this is the case, tabbar controller added the child controller into its viewControllers array.

    You can solve this by calling viewControllers?.removeLast() right after you've added your child.

    This code worked for me:

    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)
            }
        }
    }
    

    Here, instead of just calling removeLast() I've checked if the childVC was actually in that array. Just to be on the safer side.