UISplitViewController programmatically without nib/xib

Objective CIpadUisplitviewcontroller

Objective C Problem Overview


I usually create my projects without IB-stuff. The first thing I do is to strip off all references to xibs, outlets updated plist, etc and so forth. No problems, works great (in my world)!

Now, I just installed 3.2 and tried to develop my first iPad app. Following same procedure as before, I created a UISplitView-based application project and stripped off all IB-stuff. Also, I followed the section in Apple's reference docs: Creating a Split View Controller Programmatically, but nevertheless, the Master-view is never shown, only the Detail-view is (no matter what the orientation is). I really have tried to carefully look this through but I cannot understand what I have missed.

Is there a working example of a UISplitViewController without the nibs floating around somewhere? I have googled but could not find any. Or do you know what I probably have missed?

Objective C Solutions


Solution 1 - Objective C

Declare your splitviewcontroller in your delegate header, use something like this in your didfinishlaunching

ensure you add the UISplitViewControllerDelegate to the detailedViewController header file and that you have the delegate methods aswell. remember to import relevant header files

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{    

    splitViewController = [[UISplitViewController alloc] init];

    rootViewController *root = [[rootViewController alloc] init];
    detailedViewController *detail = [[detailedViewController alloc] init]; 

    UINavigationController *rootNav = [[UINavigationController alloc] initWithRootViewController:root];

    UINavigationController *detailNav = [[UINavigationController alloc] initWithRootViewController:detail];

    splitViewController.viewControllers = [NSArray arrayWithObjects:rootNav, detailNav, nil];
    splitViewController.delegate = detail;

    [window addSubview:splitViewController.view];

EDIT - as per Scott's excellent suggestion below, don't add to the windows subview, instead

    [self.window setRootViewController:(UIViewController*)splitViewController];  // that's the ticket
    [window makeKeyAndVisible];
    return YES;
}


//detailedView delegate methods
- (void)splitViewController:(UISplitViewController*)svc 
     willHideViewController:(UIViewController *)aViewController 
          withBarButtonItem:(UIBarButtonItem*)barButtonItem 
       forPopoverController:(UIPopoverController*)pc
{  
	[barButtonItem setTitle:@"your title"];

	
	
	self.navigationItem.leftBarButtonItem = barButtonItem;
}


- (void)splitViewController:(UISplitViewController*)svc 
     willShowViewController:(UIViewController *)aViewController 
  invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
	self.navigationItem.leftBarButtonItem = nil;
}

I also prefer code to IB ;-)

Solution 2 - Objective C

Oldish thread, but thought I'd spare reader time + grief when the above technique fails to produce a UISplitViewController that responds correctly to device orientation change events. You'll need to:

  1. Ensure all subordinate views respond properly in shouldAutorotateToInterfaceOrientation. Nothing new here.

  2. Rather than add the UISplitViewController's view to the main window,

    [window addSubview:splitViewController.view];   // don't do this
    

instead set the main window's root controller to the UISplitViewController:

    [self.window setRootViewController:(UIViewController*)splitViewController];  // that's the ticket

Adding the splitviewcontroller's view as a subview of the main window (barely) allows it to co-present with sibling views, but it doesn't fly with UISplitViewController's intended use case. A UISplitViewController is a highlander view; there can only be one.

Solution 3 - Objective C

Swift 5.2

iOS 13

Both master and detail view controllers are embedded in navigation controllers

    let splitViewController =  UISplitViewController()
    splitViewController.delegate = self
    let masterVC = MasterViewController() 
    let detailVC = DetailViewController()
    let masterNavController = UINavigationController(rootViewController: masterVC)
    let detailNavController = UINavigationController(rootViewController: detailVC)
    splitViewController.viewControllers = [masterNavController,detailNavController]

You can put this code in your AppDelegate's (or in SceneDelegate if your target is iOS 13.0+)didFinishLaunchingWithOptions function. Just remember to make the splitViewController your rootViewController like this

    self.window!.rootViewController = splitViewController

Solution 4 - Objective C

I had just met the same problem. make sure that your child viewController of splitview can Autorotate to interface orientation.

you can change the function in your childViewController like this:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

then the master view will be shown.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteveView Question on Stackoverflow
Solution 1 - Objective CNik BurnsView Answer on Stackoverflow
Solution 2 - Objective CScott HonjiView Answer on Stackoverflow
Solution 3 - Objective CBartosz KunatView Answer on Stackoverflow
Solution 4 - Objective Cziqian huView Answer on Stackoverflow