Search code examples
objective-cuisplitviewcontroller

UIViewController loading a UISplitViewController


I have a UINavigationController as my rootViewController, which contains a UIViewController (which I will call projects for the sake of this discussion). In Projects, I have a button, which when clicked, I want to load a UISplitViewController - preferably sliding up from the bottom, although this is just a nice-to-have feature.

In the UISplitViewController, I have a "Close" button which I want to remove the UISplitViewController re-showing Projects.

From what I have read, UISPlitViewControllers must be the rootViewControllers. With that in mind, my code so far is as follows.

AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    ...

    // LOAD THE PROJECTS PANEL ROOT VIEW CONTROLLER INTO THE WINDOW
    ProjectsListViewController *projects = [[ProjectsListViewController alloc] init];

    navigationController = [[UINavigationController alloc] initWithRootViewController:projects];

    [window setRootViewController:navigationController];
    [window makeKeyAndVisible];

    return YES;
   }

ProjectsViewController

-(IBAction)loadDetails
{    
    ProjectNavigationController *projectNavPanel = [[ProjectNavigationController alloc] init];
    ProjectDetailController *projectDetailPanel = [[ProjectDetailController alloc] init];
    ProjectSplitViewController *splitRootController = [[ProjectSplitViewController alloc] init];

    [splitRootController setViewControllers:[NSArray arrayWithObjects:projectNavPanel, projectDetailPanel, nil]];

    [[self view] removeFromSuperview];
    [[appDelegate window] setRootViewController:splitRootController];
}

UISplitViewController Naviagaion

- (void)loadProjects
{
    // LOAD THE PROJECTS LIST BACK INTO VIEW
    ProjectsListViewController *projectsList = [[ProjectsListViewController alloc] init];

    [[[self parentViewController] view] removeFromSuperview];
    [[appDelegate window] setRootViewController:projectsList];
}

Now, I know this is wrong, and unsurprisingly it is having adverse effects on other methods. In fact, as I type this, I noticed that the Projects page is being loaded in a navigationController on launch, but placed directly on the window when the splitViewController is closed. Can anyone help me by explaining the correct method of achieving this?

Thanks


Solution

  • Apple say that a UISplitViewController must be the topmost view controller in your app, and that it must be there for the entire lifetime of your app. As you've noticed, if you ignore this, everything can break.

    There are some alternatives out there that don't break this way, e.g. MGSplitViewController. Google around. If you have the time, you could even cook your own implementation of a split view controller and be in complete control.

    If you really want to use Apple's UIsplitViewController in "crazy" ways, then you can install it as root VC (as Apple demand), and have it at the root all the time, but then show other UIs modally over the top of it. Then hide the modal UI to make the split view controller appear. This is nasty and hacky though.

    A while back I asked a related question that may be of interest:

    Best way to switch between UISplitViewController and other view controllers?