Search code examples
uisplitviewcontrolleruipopovercontroller

Implementing a UISplitViewController Master Detail Application - UIPopOverController is null until rotation.


I am trying to implement a simple UISplitViewController where when in portrait mode the master view is hidden and appears with a button in a popover.

My AppDelegate is set up like this:

       - (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;
            splitViewController.presentsWithGesture = NO;

            // Add the split view controller's view to the window and display.
            [self.window setRootViewController:self.splitViewController];

[window makeKeyAndVisible];

        return YES;
    }

in FirstDetailViewController I set up a button like this:

UIImage *buttonImage = [UIImage imageNamed:@"button-menu.png"];
    UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [aButton setImage:buttonImage forState:UIControlStateNormal];
    aButton.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
    [aButton addTarget:self action:@selector(showNavigation) forControlEvents:UIControlEventTouchUpInside];
    aBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aButton];
    self.appDelegate.rootPopoverButtonItem = aBarButtonItem;

showNavigation looks like this:

-(void)showNavigation{

    NSLog(@"I am in show navigation and pc=%@",self.popoverController);

    [self.popoverController presentPopoverFromRect:self.view.frame
                                            inView:self.view
                          permittedArrowDirections:UIPopoverArrowDirectionAny
                                          animated:YES];
}

When I initially load the app and press the button I get an NSLog of

I am in show navigation and pc=(null)

And the pop over dosen't show. Now when I rotate the device to landscape mode, and then back to portrait, the master view hides and shows as expected, and the button now works in portrait mode.

Here is the code that handles the rotation:

- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {


    [[self navigationItem] setLeftBarButtonItem:aBarButtonItem];
    [self setPopoverController:pc];
    self.appDelegate.rootPopoverButtonItem = aBarButtonItem;

}


// 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 {
    [[self navigationItem] setLeftBarButtonItem:nil];
    [self setPopoverController:nil];
    self.appDelegate.rootPopoverButtonItem = aBarButtonItem;

}

How do I get the popovercontroller to not be null before any rotation occurs?


Solution

  • Ok turns out I had an if in my willHideViewController which did not include the [self setPopoverController:pc]; line. duh!