Ниже мое решение. Он начинается аналогично решению Greenisus, перехватывая обработчик событий кнопки панели инструментов UISplitViewController
. Я использую флаг в своем контроллере, чтобы отслеживать, открыт ли поповер или нет. Наконец, для обработки случая, когда пользователь открывает всплывающее окно, а затем закрывает его, щелкая за пределами всплывающего окна, я реализую протокол UIPopoverControllerDelegate
.
Во-первых, интерфейс контроллера:
@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;
Я использую _svcAction и _svcTarget, чтобы устранить беспокойство Гринисуса о том, что он может не вызывать нужную функцию.
Ниже моя реализация. Для краткости я опустил код, который создает экземпляр UISplitViewController и подпредставлений. Отображается весь связанный с показом / скрытием код.
//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];
}
Вот моя функция, которая реагирует на щелчок панели инструментов. Это обрабатывает случай, когда пользователь нажимает и повторно нажимает кнопку панели инструментов.
-(void) svcToolbarClicked: (id)sender
{
if(_popoverShowing)
{
[_popover dismissPopoverAnimated:TRUE];
}
else
{
//Perform the default SVController implementation
[_svcTarget performSelector:_svcAction];
}
//Toggle the flag
_popoverShowing = !_popoverShowing;
}
Некоторые функции из 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;
}
Приведенного выше кода достаточно для большинства случаев. Однако если пользователь открывает всплывающее окно, а затем закрывает его, щелкая в другом месте экрана, логическое значение _popoverShowing
будет содержать неверное значение, что заставит пользователя дважды нажать кнопку на панели инструментов, чтобы повторно открыть всплывающее окно. Чтобы исправить это, реализуйте метод UIPopoverControllerDelegate
, как показано ниже.
//UIPopoverControllerDelegate method
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
_popoverShowing = FALSE;
_popover = nil;
}
Это заняло у меня целую вечность, чтобы разобраться, пролистывая документы и (я думаю) большинство вопросов UISplitViewController по StackOverflow. Я надеюсь, что кто-то найдет это полезным. Если это так, я желаю очки репутации. ; -)