Home > iPad, Objective-C > UISplitViewController, MultipleDetailViews with Navigation Controller

UISplitViewController, MultipleDetailViews with Navigation Controller

January 28th, 2011 Leave a comment Go to comments

this tutorial shows how to have navigation controller in both master view and detail view of UISplitViewController.

Created new project with splitview template in Xcode.
Now first remove splitviewcontroller in mainwindow.nib,since we are creating split view controller programmatically .now in your appDelegate method

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
 
    // Override point for customization after app launch.
        self.splitViewController =[[UISplitViewController alloc]init];
	self.rootViewController=[[RootViewController alloc]init];
	self.detailViewController=[[FirstDetailViewController alloc]init];
 
	UINavigationController *rootNav=[[UINavigationController alloc]initWithRootViewController:rootViewController];
    UINavigationController *detailNav=[[UINavigationController alloc]initWithRootViewController:detailViewController];
 
	self.splitViewController.viewControllers=[NSArray arrayWithObjects:rootNav,detailNav,nil];
	self.splitViewController.delegate=self.detailViewController;
 
    // Add the split view controller's view to the window and display.
    [window addSubview:self.splitViewController.view];
    [window makeKeyAndVisible];
 
    return YES;
}

this will make master and detail of splitview as navigation controller.

Make two detail view controller first and second.

the main code for replacing detail navigation stack with view controller is

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 
    /*
     When a row is selected, set the detail view controller's detail item to the item associated with the selected row.
     */
	NSUInteger row = indexPath.row;
    [self.appDelegate.splitViewController viewWillDisappear:YES];
	NSMutableArray *viewControllerArray=[[NSMutableArray alloc] initWithArray:[[self.appDelegate.splitViewController.viewControllers objectAtIndex:1] viewControllers]];
	[viewControllerArray removeLastObject];
 
    if (row == 0) {
		self.firstDetailViewController=[[[FirstDetailViewController alloc] init]autorelease];
		[viewControllerArray addObject:self.firstDetailViewController];
		self.appDelegate.splitViewController.delegate = self.firstDetailViewController;
 
	}
 
    if (row == 1) {
		self.secondDetailViewController=[[[SecondDetailViewController alloc]init]autorelease];
		[viewControllerArray addObject:self.secondDetailViewController];
		self.appDelegate.splitViewController.delegate = self.secondDetailViewController;
    }
	[[self.appDelegate.splitViewController.viewControllers objectAtIndex:1] setViewControllers:viewControllerArray animated:NO];	
 
	[self.appDelegate.splitViewController viewWillAppear:YES];
	[viewControllerArray release];
 
   }

done You can download the code below
so now you have both of your view controller of UISplitViewController with navigation controller
MultipleDetailViewsWithNavigator

 

Categories: iPad, Objective-C
  1. Viraj
    March 16th, 2011 at 12:02 | #1

    Hello Kshitiz Ghimire, The link to the sample code appears to be broken.
    Can you fix it ?
    Thanks for the tutorial.

    • admin
      March 16th, 2011 at 12:21 | #2

      done , thank you for letting me know

  2. ash
    March 23rd, 2011 at 10:18 | #3

    hello kshitiz ..this is an amazing post. but in this once i selected a view from a popovercontroller, the root button disappears and we will not go back to another view . do u know how to fix it?

    • admin
      March 24th, 2011 at 16:07 | #4

      Fixed now

  3. April 29th, 2011 at 00:56 | #5

    Hey!

    I get an runtime error in the below method, because toolbar is not exist.

    - (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
    {
    NSMutableArray *items = [[self.toolbar items] mutableCopy];
    [items removeObjectAtIndex:0];
    [self.toolbar setItems:items animated:YES];
    [items release];
    self.popoverController = nil;
    }

  4. April 29th, 2011 at 00:58 | #6

    actually the function is in DetailViewController.m

  5. YUVARAJ.M
    June 1st, 2011 at 18:55 | #7

    Great Post. Thank you my friend. You saved my day.

  6. Jan
    June 8th, 2011 at 13:01 | #8

    Hello

    thx for this post!
    I am a newbi and so i have a question ;-)

    what is this code snippet in the file FirstDetailViewController.m on top doing? is it a composition? but of what… i do not understand and way you do not the same in the SecondDetailViewController.m

    @interface FirstDetailViewController ()
    @property (nonatomic, retain) UIPopoverController *popoverController;

    @end

    thx you

    • admin
      June 9th, 2011 at 00:30 | #9

      hi it is same thing as second detailviewcontroller , just a different way. you can follow any way. actually when you you use default template from code it does in that way , but it is your choice

  7. July 19th, 2011 at 13:37 | #10

    Hello
    Thx for this post!.I faced one problem,When i click inside Popover it does not close popover.
    [popoverController dismissPopoverAnimated:YES];

    delegate not working properly.Can you help me this problem

  8. July 31st, 2011 at 02:36 | #11

    Hello Kshitiz Ghimire,
    When i click inside Popover it does not close popover.
    [popoverController dismissPopoverAnimated:YES];

    delegate not working properly.Can you help me this problem.

    Please provide any steps .
    Can you update from your end

  9. Alberto
    August 3rd, 2011 at 19:33 | #12

    Does anyone solved the problem of dismissing the popover?
    Thank

  10. Dave
    September 9th, 2011 at 20:31 | #13

    This approach works very well, thanks! Unfortunately, I too am unable to figure out how to dismiss the popover. I understand that I must keep a reference to the popover somewhere so that I can send it the dismiss message.

    What I can’t figure out is where/how to create and store the reference to the popover controller when used with this approach. Where is the popover actually initialized: appDelegate, rootViewController, or in the detail view controllers? As noted above, sending dismiss to the property of the detail views does not seem to work.

  11. Dave
    September 10th, 2011 at 06:40 | #14

    Ok, figured it out. Well… found a way that works, can’t say that it’s best.

    The problem with the sample as it stands is that nothing actually sets the popoverController property of the detail view to point to the actual popover controller. So, you can call dissmiss on this all day long and nothing will happen; its nil.

    The example implements two methods of the splitviewcontrollerdelegate protocol in each detail view controller. The trick is to implement the third method of this protocol, “willPresentViewController”. This method is called whenever the popover is displayed. Inside your implementation of this method, set the popoverController property of your class to the “pc” that gets passed to this method. Now your property actually contains a pointer to the real popover controller.

    Back in whatever part of your code that will switch a detail view, before you switch the view, grab the value of the current detail view’s popoverController property.

    [[[[self.splitViewController.viewControllers objectAtIndex:1] viewControllers] objectAtIndex:0] popoverController];

    This points to the active pc, so you can actually send the dismiss message to it. I can’t claim that any of this is elegant or “best practice” but its working for me.

  12. Santie
    September 13th, 2011 at 21:32 | #15

    im new to the uisplitviewcontroller concept so please bare with my ignorance.

    i’m struggling to understand the relationship/hierarchy of the different controllers when using the splitviewcontroller (ie. relationship between the splitview, rootview, detailview, navcontroller…)

    i GET that the splitviewcontroller holds two viewcontrollers: one for the navigation controller (for rootview) and another for the detailview controller. but what i need is a bit more complex…

    given a list of options (rootviewcontroller), how would i add a uinavcontroller for each option? so every option has it’s own stack of detail views

    here’s what i need
    ROOTVIEW
    |— OPTION 1
    |— (uinavigationcontroller)
    | |OPT1_DETAILVIEW
    | |– OPT1_DRILLDOWNVIEW1
    | |–OPT1_DRILLDOWNVIEW2
    | |–etc
    |— OPTION 2
    |— (uinavigationcontroller)
    | |OPT2_DETAILVIEW
    | |– OPT2_DRILLDOWNVIEW1
    | |–etc
    |— OPTION 3, etc

    CAN SOMEONE HELP ME PLEASE!!!!

    PS: i’ve looked at NUMEROUS examples and none of them cater for my requirement [or I'm dumb]! FYI -neither apple’s multipleview sample nor MGSplitview helped

  13. o
    September 26th, 2011 at 10:21 | #16

    Does anyone solved the problem of dismissing the popover?
    I use this project for my first project.
    Please help me.
    Thank you very much.

  14. Priyanka
    October 5th, 2011 at 13:55 | #17

    How to dismiss the popover?

  15. iOSDev
    October 28th, 2011 at 19:42 | #18

    This answer was very helpful. thanks !!

  16. Cal Lightman
    April 21st, 2012 at 04:31 | #19

    This is nice. However, the rotations are not animated. It seems like the rotations are completed almost immediately and only the status bar rotation gets animated. Is there any way to match the rotation speed and duration of the status bar?

  17. Cal Lightman
    April 21st, 2012 at 04:42 | #20

    Sorry about my last comment. It’s not happening anymore…

  18. May 9th, 2012 at 08:35 | #21

    Hi
    For an universal iOS app (iPad and iPhone) Is it possible to make the iPad version the only device to support auto-rotate?

    the iPhone will NOT support auto rotate.

    is this possible or not?

    • admin
      May 15th, 2012 at 17:13 | #22

      ya thats possible, just detect the device and return supported interface orientation in shouldautorotate method in view controller

  19. Amit Patel
    July 16th, 2012 at 14:31 | #23

    HEllooo Frndz……!!!

    I have to use UISplitViewController.and i want to add UISplitViewController to UINavigationController. bt i can’t do this..and display message in Consol..”Application tried to push a nil view controller on target .”…….so PLZ…give me answer for how to add UINavigationController to UISplitViewController…Thanx Friend…:)

  20. Daniel
    July 30th, 2012 at 22:55 | #24

    Hi…

    Now I have this problem since a week ago and until now I understand how it is handling. thank you very much indeed for your contribution, you saved my life, not only me but several of us. Greetings from Mexico.

  21. ghouse
    August 9th, 2012 at 18:22 | #25

    hi i followed your tutorial and try to implement my own stuff like in one of the second detailview i have a button when i click on it it should push to new view controller but with the same row selected .it does but when i select another row there i am getting naviagtion button which leads to second view . why it is coming like that please help me i am looking for solution for many days

  22. memento
    August 22nd, 2012 at 15:34 | #26

    Hello !
    Fantastic work !

    This is exactly what I needed.
    But could you give me a hint, if you’re patient enough, Could you tell me what is the simplest way to push a new view controller in the detail view ?

    I tried different ways in the RootViewController.m, but I think I got it wrong.

    I know this question must seem dumb to you, but I’m a beginner at iOS programming.
    It would be so nice of you to answer this question. :)

    Alex.

  23. memento
    August 22nd, 2012 at 15:38 | #27

    To be as clear as possible, let’s say I want to put a button on the first view controller that will trigger the action of pushing another view in the detail view.

    To be honest, I’m trying to push some view controllers (forms for the user) in the detail view.

    Greetings from France.

  24. Sarath
    August 24th, 2012 at 10:30 | #28

    Hi.

    I have a problem with Popover window on 5.1 simulator. Normal typical popover window is displaying properly for 4.3 & 5.0 Simulator, But 5.1 Simulator at portrait mode displaying just like splitwindow…

    if any one solved this problem ps tell…….

  25. Daniel
    August 31st, 2012 at 05:49 | #29

    Great example. It is what I need. Just I have one question. I’ve read a lot about delegates, because I can’t completely understand that concept. What I read, is “delegates” are methods declared inside a protocol. The class that declares that “delegate” need to implement that methods. In this example. you don’t declare any protocol, but declare references to your AppDelegate in every ViewController. Is this because in you AppDelegate are declared the SplitViewController?
    Thanks

  26. March 21st, 2013 at 17:24 | #30

    Unfortunately, I too am unable to figure out how to dismiss the popover. plz help

  27. March 22nd, 2013 at 17:01 | #31

    hi, I Have Solved both situations…

    1) id didSelectRowAtIndexPath of RootViewController
    [[NSNotificationCenter defaultCenter] postNotificationName:@”MASTERROWSELECTED”
    object:nil];

    2) then in FirstDetailViewController ‘s viewWillAppear and SecondDetailViewController ‘s viewDidLoad

    [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(dismissPop) name:@”MASTERROWSELECTED” object:nil];

    self.navigationItem.leftBarButtonItem = appDelegate.rootPopoverButtonItem;

    also implement – (void)dismissPop
    {

    if(self.interfaceOrientation == UIInterfaceOrientationPortrait)
    {

    //self.popover is your reference to master view pop
    if([self.popoverController isPopoverVisible])
    {
    [[self navigationItem] setLeftBarButtonItem:self.appDelegate.rootPopoverButtonItem ];
    [self.popoverController dismissPopoverAnimated:YES];

    }
    }

    }

    before these
    set
    self.appDelegate.rootPopoverButtonItem = barButtonItem;

    in splitViewController of FirstDetailViewController

    working perfect for me…..might be not the best practice

  28. Avi
    October 31st, 2013 at 20:30 | #32

    Thank u very much, this is very helpful :)

  1. No trackbacks yet.