在纵向模式下按下新视图控制器后,iOS UISplitViewController的Popover控制器按钮消失

时间:2011-10-25 06:50:49

标签: objective-c ios ipad

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

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

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

  
    

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

         

//detailPane is my DetailViewController

  

所有在横向模式下都能很好地工作。但是,我无法使UISplitViewController在肖像模式下工作,也就是说,当我在portait模式下启动并使用应用程序时,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;   
}

非常感谢任何提示或帮助。 感谢。

4 个答案:

答案 0 :(得分:4)

刚刚想出了一个新的解决方案。

子类UINavigationController并实施UISplitViewControllerDelegate。将此类的实例设置为splitViewController的右侧ViewController。每次要从主

更改详细视图控制器时
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

这对我有用,我可以避免定义一个孔协议并将主设置为委托,这是一个很大的权衡。希望它有所帮助。

答案 1 :(得分:3)

如果你仍然需要它:

http://developer.apple.com/library/ios/#samplecode/MultipleDetailViews/Introduction/Intro.html

我对我的来源做了什么(我有类似的设置)来解决它:

我有主视图控制器(在我的情况下是UITableViewController)是UISplitViewController的委托。在UISplitViewControllers的两个委托方法中(因此这将在您的主视图控制器实现中),您将在类中保存popupviewcontroller和barbuttonitem。现在,如果您更改了详细信息viewcontroller,请执行以下操作:

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

您的每个detailsViewControllers应遵守的委托。你会这样实现:

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

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

如果这有助于您,请告诉我。

答案 2 :(得分:2)

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

目前尚不清楚action:选择器会导致UISplitViewController在弹出窗口中显示MasterViewController。当我最终弄清楚这一点时,通过检查调试器中的BarButtonItem,我意识到为什么解决这个问题是如此棘手:action:选择器没有在Apple的iOS SDK中记录。哎呀。

试试这个:

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

您可能希望使用检查窗口处于纵向模式的条件来包围此代码,例如if ([self interfaceOrientation] == UIInterfaceOrientationPortrait)

答案 3 :(得分:0)

当您设置放置在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;