swiftuiviewcontrolleruinavigationcontrollerchildviewcontroller

Working with 2 UINavigationControllers inside a ViewController as Child causes only 1 to respond, the other does not respond


I'm working with a project where I start with a ContainerViewController having 2 controllers added as a child:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    guard let scene = (scene as? UIWindowScene) else { return }
    window = UIWindow(windowScene: scene)
    window?.rootViewController = ContainerViewController()
    window?.makeKeyAndVisible()
}

The ContainerViewController:

class ContainerViewController: UIViewController {


var panGestureRecognizer: UIPanGestureRecognizer!


private var menuWidth: CGFloat = UIScreen.main.bounds.width - 50

let menuController = SideMenuViewController()
let mainController = MainViewController()

override func viewDidLoad() {
    super.viewDidLoad()
    addChildVCs()
    
    panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        view.addGestureRecognizer(panGestureRecognizer)
}

private func addChildVCs() {
    
    addChild(menuController)
    menuController.view.frame = CGRect(x: 0 - view.frame.size.width, y: 0, width: menuWidth, height: view.frame.size.height)
    view.addSubview(menuController.view)
    menuController.delegate = self
    menuController.didMove(toParent: self)
    
    addChild(mainController)
    mainController.delegate = self
    view.addSubview(mainController.view)
    mainController.didMove(toParent: self)
}

With this panGesture I just show/hide a SideMenu, nothing strange here.

Inside this MainViewController, I have a TabBarController named mainController and another UINavigationController that store user conversations, named ConversationViewController(), both added as a child like this:

class MainViewController: UIViewController {

let mainController = MainTabController()
let conversationNavigationController = UINavigationController(rootViewController: ConversationViewController())

override func viewDidLoad() {
    super.viewDidLoad()
    addChildVCs()
}

private func addChildVCs() {
    addChild(mainController)
    mainController.menuDelegate = self
    view.addSubview(mainController.view)
    mainController.didMove(toParent: self)
    
    addChild(conversationNavigationController)
    conversationNavigationController.view.frame = CGRect(x: view.frame.size.width, y: 0, width: view.frame.size.width, height: view.frame.size.height)
    view.addSubview(conversationNavigationController.view)
    conversationNavigationController.didMove(toParent: self)
    
}

The conversationNavigationController origin.x point is starting at the end of the mainController (tabBar) so I can panGesture to the right and show/hide this other UINavigationController.

The problem is when I start the execution I can interact with the mainController(tabBarController) but when I swipe to the right and I have the conversationNavigationController on screen, it doesn't respond to any actions.

Basically I'm working with 2 navigationControllers at the same time but I don't understand why 1 is working and the other one does not respond to any actions.

Any clue on what's the problem? I can provide more code if needed!

Thanks in advance


Solution

  • If you just add your child view controller's content views to your MainViewController's content view, Auto Layout doesn't know what to do with them. At the drop of a hat, Auto Layout will resize your child view controllers in unexpected and undesired ways.

    I'm guessing that your view controllers' view frames are getting messed up. It might be that there is some other problem with your view controllers that's preventing them from responding to events, but first I would rule out view layout problems.

    I would suggest adding container views to your main view controller, including Auto Layout constraints to put them where you want them.

    Then add your child view controllers' views as subviews of those container views, and anchor all 4 edges of your child view controller's view to the edges of their parent views.

    When you're first working on it, it is worth adding a borderWidth and borderColor to your different views' layers so you can see what's going on.