Search code examples
iosswift2uitabbarcontrollerios9xcode7

Presented TabBarController disappearing after attempted segue


General setup of connected viewController to tabBarController

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.


Solution

  • 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!