Search code examples
swiftdelegatesstoryboardviewcontrollertabbarcontroller

Swift 3+: Multiple Storyboards with TabBarController. Set TabBarController Tab, Segue to desired ViewController


Working in multiple storyboards. Getting from point A->TabBarController(tab 2)->NavigationControllerA->StoryboardReference->NavigationControllerB->ViewControllerA->ViewControllerB. No need for data passing.

My tab bar controller is set up in its own storyboard, with each tab going through a navigation controller to a storyboard reference. Then the storyboard reference links to another storyboard (obv.), and through a navigation controller to ViewControllerA. I then want to go to performSegue to ViewControllerB. This is all done from a UIViewController Extension. From what I've been reading, I should approach like this:

    let tab = 2
    let sbOne = UIStoryboard(name: "Main", bundle: nil)
    let tabBarController = sbOne.instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    appDelegate.window?.rootViewController = tabBarController
    tabBarController.selectedIndex = tab

    let sbTwo = UIStoryboard(name: "sbTwo", bundle: nil)
    let viewControllerA = sbTwo.instantiateViewController(withIdentifier: "ViewControllerA")
    performSegue(withIdentifier: "toViewControllerB", sender: self)

I receive NSInvalidArgument: Point A "has no segue with identifier 'toViewControllerB'"


Solution

  • Swift 3+ I’d be surprised if this is the best answer but this is the only solution that worked. A bit of my problem stemmed from lack of understanding. But the concept I arrived at was to separate the functions into two parts. Setting the tabbarcontroller tab, then segueing to the destination using a variable struct. I ended up setting a struct at Point A.

    struct Destination {
        static var currentID = Int()
    }
    

    And on button press I would set the variable with this and then and call the function below:

    Destination.currentID = currentID
    goToViewControllerA()
    

    Then using part of the code I had before I could set the tabbar Controller as the root view controller and go to ViewControllerA (the first view controller) on the selected tab. This is done in an uiviewcontroller extension but can also be done in a function in Point A.

    goToViewControllerA(){
    let tab = 2
    let sbOne = UIStoryboard(name: "Main", bundle: nil)
    let tabBarController = sbOne.instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    appDelegate.window?.rootViewController = tabBarController
    tabBarController.selectedIndex = tab
    }
    

    It’s then just a matter of checking if the struct static var is set, and segueing to the destination controller (ViewControllerB). This is done in ViewControllerA, or if you have to segue through multiple view controllers you could model your function on each viewcontroller using this in the viewdidload.

    If Destination.currentID != Int() {
        performSegue(withIdentifier:“toViewControllerBSegue”, sender:self)
    }
    

    I’d love to learn a better way of doing this if it exists.