UISplitViewController inside UITabBarController in iOS6

Over the recent break between fall and spring semesters I worked to build my first GUI for the iPad. The app I am working on (Clyde’s Garden Planner) is a universal app which needs to support all iOS devices. I was following the same basic layout of the iPhone GUI which uses a UITabBarController as the root view controller. However, difficulty arose when I set some of the tab bar subviews to instances of UISplitViewController.

I started researching the problem and found that having a UISplitViewController was, at least at one time, prohibited by Apple. I also found some people saying that those statements had been removed from the Apple documentation. I looked and couldn’t find anything prohibiting this behavior in current Apple documentation so I am inclined to say it is no longer prohibited. However, just because it may not be explicitly prohibited anymore doesn’t mean it works…

I would get several layout issues when switching to one of the split views after a rotation had occurred on a non-split view tab.

Screen Shot 2013-01-20 at 7.36.08 PMImage 1. Example layout error

I found some solutions people had come up with which involved subclassing UISplitViewController and subscribing to event notifications or subclassing UIViewController and mimicking the functionality of the split view controller. I tried implementing one of these in my project but I still had some issues (probably due to the iOS6 layout manager).

I knew the problems occurred because the split view controllers were not receiving certain events that they would be if they were visible so I started playing around with forwarding events, etc and eventually came up with a solution.

My solution is shown in the following two Gists from GitHub.

Basically I first subclass UITabViewController and inside I forward rotation events to any child view controllers that are of the UISplitViewController kind. Then I subclassed UISplitViewController and forced one of the delegate methods to be called (splitViewController:willShowViewController:invalidatingBarButtonItem:). I’m not sure why I still had to force that delegate method to be called but I believe it must have something to do with the view not currently being visible. Subclassing both these objects is explicitly allowed by Apple as of iOS6.

You can find these objects in my GitHub project DCToolKit. If anyone has any insight or has solved this a better way in iOS6 please feel free to comment or better yet fork my project and submit a pull request.

UITabBarController Documentation
UISplitViewController Documentation
UIViewController Documentation


9 thoughts on “UISplitViewController inside UITabBarController in iOS6

  1. I want to make sure that I understand everything that you did. I walked through your code at github. I don’t see where you reference either of your subclasses for SplitViewController or TabBarController in you Test App. My understanding is that at least prior to IOS 6, we were not supposed to subclass SplitViewController and it was supposed to be a root controller. I came to your article trying to figure out if I could have a TabBarController with multiple SplitViewControllers. Thanks for sharing your experiences.

    • Hi,
      Yes the test app was something I was going to work on more later as I added to my library. Sorry it is not yet helpful!
      I implemented the custom controllers in my project just like a normal UITabBarController and UISplitViewController; however, the UISplitViewController is added as one of the tabbar’s children. I would recommend following some tutorials/sample code for setting up regular UITabBarControllers and UISplitViewControllers then run and see if you get rotation errors. If you do just drop in my classes as direct replacements for the originals.
      You are correct before iOS6 subclassing these objects was “discouraged” (people still did it some anyway).
      Thanks for your comment and glad this has been helpful to someone else!

  2. Hi,
    I ran across your answer in stackoverflow so i decided to take a look at your blog here. First of all, thanks for sharing your knowledge here. I’m still a newbie in iOS and am facing lots of difficulties. Have you ever experienced in pushing a splitview controller from another view controller? If so, could you tell me how to achieve that? Cuz i got stuck with this and my app wouldnt get finished without it. And I plan on using tab bar controller as a second approach if somehow I can’t figure out a way to my problem.

    Thanks. Cheers!

    • Hi,
      I would go through some tutorials on using UISplitViews and practice up a bit. Once you are comfortable setting them up and using them you should be able to push them on the view controller stack like anything else. The only difference is that they require more setup which a bit of time working with them will help you understand.

  3. Hi,
    I like your approach. I tried also this one that works perfectly for me:
    But I didn’t released any app with that… Has any one an app with an UISplitViewController on a UITabBarController already on AppStore?

    I’m still finding on the documentation, that the UISplitViewController has to be the root of the APP.

    “A split view controller must always be the root of any interface you create. In other words, you must always install the view from a UISplitViewController object as the root view of your application’s window. The panes of your split view interface may then contain navigation controllers, tab bar controllers, or any other type of view controller you need to implement your interface. Split view controllers cannot be presented modally.”

    Thanks and cheers

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s