Short synopsis (XCode 7.2, Swift2, iOS 9.2 as target):
1) In a first.storyboard, I have a single viewController.
2) In a second.storyboard, I have a tabbarController, with multiple navigationControllers with tableviewControllers (see attached image). Also of note is when second.storyboard is the one used on launch, everything works correctly.
3) the main UI for the app is in the first.storyboard, and I want to present the tabbarcontroller in the second.storyboard
4) No matter which way I present it (storyboard reference/segue, presentViewController, showViewController), the tabbarcontroller and all the initial views work, but if I tap a tableviewcell to segue to another view, the whole tabbarcontroller and contents disappear, leaving me back at the viewcontroller in first.storyboard.
I can cheat, and set the rootViewController manually and things seem to work
let sb = UIStoryboard(name: "second", bundle: nil)
let navController = sb.instantiateViewControllerWithIdentifier("secondIdentifier") as! UITabBarController
UIApplication.sharedApplication().keyWindow?.rootViewController = navController
And I suspect I can add an animation to this to not have the transition not be so stark. But this seems like something I shouldn't have to do, and kind of a pain to troubleshoot in the future. Am I missing something fundamental in making this work?
EDIT: Video of it not working https://youtu.be/MIhR4TVd7CY
NOTE: The last app I made originally targeted iOS4, and I did all the views programatically. It seemed like all the updates to IB and segues etc would make life more manageable (and for the most part that has been true), but this is still my first foray in to it, so I may be missing some important points of information to describe the issue.
I have found a superior way to deal with this: UIViewControllerTransitioningDelegate
It's a bit of extra work to implement, but it produces a "more correct" result.
My solution was to make a custom UIStoryboardSegue that will do the animation as well as set the rootViewController.
import UIKit
class changeRootVCSeguePushUp: UIStoryboardSegue {
override func perform() {
let applicationDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let sourceView = self.sourceViewController.view
let destinationView = self.destinationViewController.view
let sourceFrame = sourceView.frame
let destinationStartFrame = CGRect(x: 0, y: sourceFrame.height, width: sourceFrame.width, height: sourceFrame.height)
let destinationEndFrame = CGRect(x: 0, y: 0, width: sourceFrame.width, height: sourceFrame.height)
destinationView.frame = destinationStartFrame
applicationDelegate.window?.insertSubview(self.destinationViewController.view, aboveSubview: self.sourceViewController.view )
UIView.animateWithDuration(0.25, animations: {
destinationView.frame = destinationEndFrame
}, completion: {(finished: Bool) -> Void in
self.sourceViewController.view.removeFromSuperview()
applicationDelegate.window?.rootViewController = self.destinationViewController
})
}
}
I could not find a way in interface builder, or in code other than changing the rootViewController to get this working. I would end up with various random navigation issue like overlapping navigation bars, segue animations not working correctly until I changed tabs, full on lockups with no information in the console, etc.
I have previously presented a tabBarcontroller modally (without changing rootviewController), but everything was done in code (working as of ios7 and objective-c). No clue what is going on under the covers when the view hierarchies are made in a storyboard, but wondering if this is perhaps a bug.
Thanks to multiple other answers here on stackoverflow to get to mine!