Below is my solution. It starts out similar to greenisus' solution, by hooking the UISplitViewController
's toolbar button event handler. I use a flag in my controller to track whether the popover is open or not. Finally, to handle the case where the user opens the popover, then closes it by clicking outside the popover, I implement the UIPopoverControllerDelegate
protocol.
First, the controller interface:
@interface LaunchScene : NSObject <UISplitViewControllerDelegate, UIPopoverControllerDelegate>
{
UISplitViewController* _splitViewController; //Shows list UITableView on the left, and details on the right
UIToolbar* _toolbar; //Toolbar for the button that will show the popover, when in portrait orientation
SEL _svcAction; //The action from the toolbar
id _svcTarget; //The target object from the toolbar
UIPopoverController* _popover; //The popover that might need to be dismissed
BOOL _popoverShowing; //Whether the popover is currently showing or not
}
-(void) svcToolbarClicked: (id)sender;
I use _svcAction and _svcTarget to addess greenisus' worries that he might not be calling the right function.
Below is my implementation. For brevity, I have omitted the code that instantiates the UISplitViewController and the subviews. All the show/hide related code is shown.
//the master view controller will be hidden so hook the popover
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc
{
_popoverShowing = FALSE;
if(_toolbar == nil)
{
//set title of master button
barButtonItem.title = @"Title goes here";
//Impose my selector in between the SVController, and the SVController's default implementation
_svcTarget = barButtonItem.target;
_svcAction = barButtonItem.action;
barButtonItem.target = self;
barButtonItem.action = @selector(svcToolbarClicked:);
//create a toolbar
_toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 1024, 44)];
[_toolbar setItems:[NSArray arrayWithObject:barButtonItem] animated:YES];
}
//add the toolbar to the details view (the second controller in the splitViewControllers array)
UIViewController* temp = [_splitViewController.viewControllers objectAtIndex:1];
[temp.view addSubview:_toolbar];
}
Here is my function, that responds to the toolbar click. This handles the case where the user taps and re-taps the toolbar button.
-(void) svcToolbarClicked: (id)sender
{
if(_popoverShowing)
{
[_popover dismissPopoverAnimated:TRUE];
}
else
{
//Perform the default SVController implementation
[_svcTarget performSelector:_svcAction];
}
//Toggle the flag
_popoverShowing = !_popoverShowing;
}
Some functions from UISplitViewControllerDelegate
//the master view (non-popover) will be shown again (meaning it is going to landscape orientation)
- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)button
{
//remove the toolbar
[_toolbar removeFromSuperview];
}
// the master view controller will be displayed in a popover (i.e. the button has been pressed, and the popover is about to be displayed.
//Unfortunately triggers when the popover is ALREADY displayed.
- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController
{
_popover = pc; //Grab the popover object
_popover.delegate = self;
}
The above code is sufficient for most cases. However, if the user opens the popover, then dismisses by clicking elsewhere on the screen, the _popoverShowing
boolean will contain an incorrect value, which will force the user to tap the toolbar button twice to re-open the popover. To fix this, implement the UIPopoverControllerDelegate
method, like the snippet below.
//UIPopoverControllerDelegate method
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
_popoverShowing = FALSE;
_popover = nil;
}
This took me forever to figure out, digging through the docs and (I think) most of the UISplitViewController questions on StackOverflow. I hope somebody finds it useful. If so, I covet reputation points. ;-)