1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

How to use splitViewController in one TabBarController

Discussion in 'iPhone/iPad Programming' started by mikezang, Aug 11, 2010.

  1. macrumors 6502a

    I have a tab bar controller, and I want to use a split view controller in one tab, I tried to select view controller in inspector, but there is no UISplitViewController, and I tried to inset a UISplitViewController and failed, how can I use UISplitViewController in UITabBarController?
  2. Moderator


    Staff Member

    Basically you can't do what you are trying to do: the split view controller must be the outer most controller (i.e. the one directly within the window). The best you can do is hide the over view when other tabs are selected.
  3. macrumors 6502a

    What do you mean?
  4. Moderator


    Staff Member

    I mean exactly what I said. I chose the words carefully after all.

    You must have the UISplitViewController as the top-level view controller. It will not allow it's view to be placed inside any other view controllers view. So if you want to use it you must put the tab view controller within the split view controller as either master or detail. Assuming you set the tab controller as master (the larger of the two views) you simply hide the detail view (look at the documentation) for all tabs other than the one you want to show the split on.
  5. macrumors 6502a

    Yeah, I understood your mean except last one.

    I found some samples to talk about use split in tabbar, for example, but my tabbar has others view controller, I just want to add a new tab with splitview, but I am not sure how to keep other tabs what I made in IB, that is my question


  6. Moderator


    Staff Member

    I have explained what I would do. This would prevent the problems with iOS 3.2 as discussed in one of those links. I don't use IB so you'll forgive me if I don't try and answer anything to do with that.
  7. macrumors 6502a

    Please let me know if you get something figured out with this. I have been trying to do the same thing. Unfortunately, there is rarely a time when anyone on MacRumors will answer with anything useful. They all seem to like to google whatever your question is and post a link instead of real help. And if you dare ask them for an example they get tight-lipped and think you should take a full course on programming instead of them spending 5 minutes to help. I actually found one guy who went to the trouble of posting about 5 links on how to email from within app in response to a question of how to do that, instead of just posting the UISharedApplication mailto:"@yahoo" code. Very rude folks here.
  8. macrumors 6502a

    Thanks, guy, you said what I thought!

    I have more than 20 years experience in Windows and only half year in Mac.

    I never met such forums in past years when I ask something for Windows programming, but here like you said, no experts want to answer your question, they just tell you to google, I am not sure if this is Apple's fashion or they thought they are experts and no paitiant answer anything?!

    Anyway, this way is not good for communication....
  9. macrumors newbie

    UISplitViewController *splitViewController = [[UISplitViewController alloc] init];
    [tabBarController.view addSubview:splitViewController.view];
  10. macrumors 6502a

    I got it but not complete, there is no button for popover and..., anyway, this is a little step, I will show your after I got full splitView.

    Attached Files:

  11. macrumors 6502a

    I walked one more step, now when I selected row in master view on landscape mode, the detail view will show detail information.
    The rest problem is detailView can not act for <UIPopoverControllerDelegate, UISplitViewControllerDelegate> on portrait mode.

    Do you have any suggestion?

    Attached Files:

  12. Moderator


    Staff Member

    That's not related to the tab-bar thing: you always have to add that yourself. For whatever reason Apple did not make it automatic. You may have some fun doing this on first run as you cannot assume the orientation of the device...
  13. macrumors 6502a

    I did it in my detail view controller, but I am not sure why the methods don"t be called, this is my next task. do you have any idea?
    #pragma mark -
    #pragma mark Split view support
    - (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
        barButtonItem.title = @"Master List";
        NSMutableArray *items = [[toolbar items] mutableCopy];
        [items insertObject:barButtonItem atIndex:0];
        [toolbar setItems:items animated:YES];
        [items release];
        self.popoverController = pc;
    // Called when the view is shown again in the split view, invalidating the button and popover controller.
    - (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
        NSMutableArray *items = [[toolbar items] mutableCopy];
        [items removeObjectAtIndex:0];
        [toolbar setItems:items animated:YES];
        [items release];
        self.popoverController = nil;
  14. Moderator


    Staff Member

    What is toolbar? Is it visible on the screen? I don't see it in your screenshots (unless it's the grey bar at the top of the detail: I assumed that was a navigation bar).
  15. macrumors 6502a

    The gray is toolbar, detailview has no navigation bar.
  16. Moderator


    Staff Member

    OK. Are the methods being called at all (put an NSLog in to check)? If not is the object (the detail view controller I assume) the delegate of the UISplitViewController?
  17. macrumors 6502a

    I did debug and log, they never be called.
    @interface StockDetailController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate> {
        UIPopoverController *popoverController;
        UIToolbar *toolbar;
        id detailItem;
        UILabel *detailDescriptionLabel;
  18. Moderator


    Staff Member

    You have declared that the class implements the delegate protocol. This in no way implies that the actual instance of the class is the delegate of any instance of UISplitViewController: you must set the delegate property of the split view controller instance. This is normal: it is like this for every single Cocoa/Cocoa Touch class that has a delegate.
  19. macrumors 6502a

    Thanks for your suggestion, now I got what I need.

    Attached Files:

  20. macrumors newbie

    How did you fit this splitview into tab bar?

    Mikezang, how did you get this Splitview to show up instead of Navigation or View controller when tab bar item selected? Your image show exactly what I was chasing but no info how it was done?
  21. macrumors 6502a

    Put makeSplitViewController in applicationDidLaunch method and copy master and detail view controllers from SplitViewController template.
    @interface StockManagerAppDelegate : NSObject <UIApplicationDelegate> {
        UIWindow *window;
        UITabBarController *tabBarController;
        UISplitViewController *splitViewController;
        UINavigationController *navigationController;
        StockMasterController *stockMasterController;
        StockDetailController *stockDetailController;
    @property (nonatomic, retain) IBOutlet UIWindow *window;
    @property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
    @property (nonatomic, retain) IBOutlet UISplitViewController *splitViewController;
    @property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
    @property (nonatomic, retain) IBOutlet StockMasterController *stockMasterController;
    @property (nonatomic, retain) IBOutlet StockDetailController *stockDetailController;
    #import <UIKit/UIKit.h>
    @class StockDetailController;
    @interface StockMasterController : UITableViewController {
        StockDetailController *stockDetailController;
    @property (nonatomic, retain) IBOutlet StockDetailController *stockDetailController;
    -(void) makeSplitViewController {
        NSMutableArray *controllers = [NSMutableArray arrayWithArray:tabBarController.viewControllers];
        int index = 0;
        for (UIViewController *controller in tabBarController.viewControllers) {
            if ([controller.tabBarItem.title isEqualToString:@"Stock"]) {
                stockDetailController = [[StockDetailController alloc] initWithNibName:@"StockDetailController" bundle:nil];
                stockMasterController = [[StockMasterController alloc] initWithStyle:UITableViewStylePlain]; 
                stockMasterController.navigationItem.title = date;
                stockMasterController.stockDetailController = stockDetailController;
                UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:stockMasterController] autorelease];
                splitViewController = [[UISplitViewController alloc] init];
                splitViewController.tabBarItem = controller.tabBarItem;
                splitViewController.viewControllers = [NSArray arrayWithObjects:nav, stockDetailController, nil];
                splitViewController.delegate = stockDetailController;
                [controllers replaceObjectAtIndex:index withObject:splitViewController];
        tabBarController.viewControllers = controllers;
  22. macrumors newbie

    Thank you!

    You are a lifesaver! Thanks!:)
  23. macrumors newbie

    There's no way to do this for the first tab though, to replace the first index of the tab bar controller results in an error:

    'NSRangeException', reason: '*** -[NSCFArray removeObjectAtIndex:]: index (0) beyond bounds (0)'
  24. macrumors 6502a

    Why? in my app, I used it in first tab.

    Attached Files:

  25. macrumors 6502a

    If you use it in first tab with Landscape, you have to add code as below to RootViewController.m
    (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
        self.navigationController.toolbar.hidden = YES;
        self.navigationController.navigationBar.top = 0;

Share This Page