iOS UISplitViewController的弹出框控制器按钮在纵向模式下推送新视图控制器后消失



在我的UISplitViewController应用程序中,我有

  • RootViewController -左窗格中的视图控制器。
  • DetailViewController -右窗格中的视图控制器。

当RootViewController中的一个项目(在UITableView中)被选中时,新的视图控制器将被设置为如下所示:

[detailViewController setViewControllers:[NSArray arrayWithObjects:newViewController, nil] animated:animated];

//detailPane is my DetailViewController

在横向模式下都能很好地工作。然而,我不能使UISplitViewController工作,我想在肖像模式,也就是说,RootViewController的弹出按钮不适当地出现在我的DetailViewController当我启动和使用应用程序在肖像模式。

当我在纵向模式下启动应用程序时,弹出按钮适当地出现。但是在点击弹窗中的一个项目并且在detailViewController上设置了一个新的视图控制器之后,按钮消失了。我必须旋转设备到横向,然后再回到纵向,使按钮再次出现。

我在应用程序的AppDelegate中设置了UISplitViewController的委托,如下所示:

self.splitViewController.delegate = self.detailViewController

这是我的UISplitViewControllerDelegate实现

- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem  forPopoverController: (UIPopoverController*)pc {
    NSLog(@"Will hide view controller");
    barButtonItem.title = @"Menu";
    [self.navigationItem setLeftBarButtonItem:barButtonItem];
    self.popoverController = pc;
}
- (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
    NSLog(@"Will show view controller")
    NSMutableArray *items = [self.navigationItem.leftBarButtonItems mutableCopy];
    [items removeAllObjects];
    [self.navigationItem setLeftBarButtonItems:items animated:YES];
    [items release];
    self.popoverController = nil;   
}
任何提示或帮助都是非常感激的。谢谢。

我想到了一个新的解决方案。

子类UINavigationController并实现UISplitViewControllerDelegate。设置这个类的一个实例作为splitViewController的右视图控制器。每次你想从主视图更改detail视图控制器

NewDetailViewController *newDetailVC = ....// Obtain the new detail VC
newDetailVC.navigationItem.leftBarButtonItem = [[[[self.splitViewController.viewControllers objectAtIndex:1]topViewController]navigationItem ]leftBarButtonItem];  //With this you tet a pointer to the button from the first detail VC but from the new detail VC
[[self.navigationController.splitViewController.viewControllers objectAtIndex:1]setViewControllers:[NSArray arrayWithObject:newDetailVC]];  //Now you set the new detail VC as the only VC in the array of VCs of the subclassed navigation controller which is the right VC of the split view Controller

这对我来说是有效的,我可以避免定义一个漏洞协议并将主节点设置为委托,这是一个很大的权衡。

如果你还需要的话:

http://developer.apple.com/library/ios/samplecode/MultipleDetailViews/介绍/Intro.html

我对我的源代码(我有类似的设置)做了什么来修复它:

我有主视图控制器(UITableViewController在我的情况下)是UISplitViewController的委托。在UISplitViewControllers的两个委派方法中(这将在你的主视图控制器实现中)你会在你的类中保存popupviewcontroller和barbuttonitem。现在,如果你改变你的细节视图控制器,你可以:

self.viewControllers = [NSArray arrayWithObjects:[self.viewControllers objectAtIndex:0], newDetailsViewController, nil];
UIViewController <SubstitutableDetailViewController>*vc = (UIViewController <SubstitutableDetailViewController>*)newDetailsViewController;
[vc invalidateRootPopoverButtonItem:_tableViewController.rootPopoverButtonItem];
[_createReportViewController showRootPopoverButtonItem:_tableViewController.rootPopoverButtonItem];

这里有

@protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
@end

你的每个detailsviewcontroller都应该遵守的委托。你可以这样实现:

- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
    self.navigationItem.leftBarButtonItem = barButtonItem;
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
    self.navigationItem.leftBarButtonItem = nil;
}

如果这对你有帮助,请告诉我。

我喜欢Nekto的解决方案,但它忽略了一个关键问题。

尚不清楚action:选择器将导致UISplitViewController在弹出窗口中显示MasterViewController。当我通过在调试器中检查BarButtonItem最终弄清楚这个问题时,我意识到为什么要弄清楚这个问题是如此棘手:action:选择器在苹果的iOS SDK中没有任何文档。哦。

试试这个:

UIBarButtonItem *showListView = [[UIBarButtonItem alloc] initWithTitle:@"List" style:UIBarButtonItemStyleBordered target:[self splitViewController] action:@selector(toggleMasterVisible:)];
[[detailViewController navigationItem] setLeftBarButtonItem:showListView];        

您可能想要用检查窗口是否处于纵向模式的条件包围这段代码,例如if ([self interfaceOrientation] == UIInterfaceOrientationPortrait)

当你在navigation stack上设置新的视图控制器时,可能所有的导航按钮都被重置。您可以在更改navigation stack后手动添加适当的按钮。

例如,您可以从- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc中选择创建默认弹出窗口控制器按钮的代码:

UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"Menu" style:UIBarButtonItemStyleBordered target:self action:@selector(appropriateSelector)];
[self.navigationItem setLeftBarButtonItem:barButtonItem];
self.popoverController = pc;

最新更新