Objective c iOS UISplitViewController';在纵向模式下按“新建视图控制器”后,s Popover控制器按钮消失

Objective c iOS UISplitViewController';在纵向模式下按“新建视图控制器”后,s Popover控制器按钮消失,objective-c,ios,ipad,Objective C,Ios,Ipad,在我的UISplitViewController应用程序中 RootViewController-在左窗格中查看控制器 DetailViewController-右窗格中的视图控制器 点击RootViewController中的一个项目(在UITableView中)时,将设置新的视图控制器,如下所示: [detailViewController SetViewController:[NSArray arrayWithObjects:newViewController,nil]已设置动画:已设

在我的UISplitViewController应用程序中

  • RootViewController-在左窗格中查看控制器
  • DetailViewController-右窗格中的视图控制器
点击RootViewController中的一个项目(在UITableView中)时,将设置新的视图控制器,如下所示:

[detailViewController SetViewController:[NSArray arrayWithObjects:newViewController,nil]已设置动画:已设置动画]

//detailPane是我的DetailViewController

在横向模式下,所有这些都可以很好地工作。但是,我无法使UISplitViewController在纵向模式下按我所需的方式工作,也就是说,当我在portait模式下启动和使用应用程序时,RootViewController的popover按钮在我的DetailViewController中没有正确显示

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

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

self.splitViewController.delegate=self.detailViewController

这是我的UISPlitViewController Delegate实现

- (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;   
}
非常感谢您的任何提示或帮助。
谢谢。

当您设置放置在
导航堆栈上的新视图控制器时,可能会重置所有导航按钮。更改
导航堆栈后,可以手动添加相应的按钮

例如,您可以从
-(void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController*)aViewController with barButtonItem:(UIBarButtonItem*)barButtonItem For PopOvercontroller:(UIPopoverController*)pc中拾取代码,其中创建了默认的popover控制器按钮:

UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"Menu" style:UIBarButtonItemStyleBordered target:self action:@selector(appropriateSelector)];
[self.navigationItem setLeftBarButtonItem:barButtonItem];
self.popoverController = pc;
如果您仍然需要它:

我对我的源代码所做的(我的设置与您类似)修复了它:

我让主viewcontroller(在我的例子中是UITableViewController)成为UISplitViewController的代理。在uisplitviewcontroller的两个委托方法中(这将在主viewcontroller实现中),您将在类中保存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];
每个DetailsViewController都应遵守的委托。您可以这样实现:

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

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

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

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

子类
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

这对我来说是可行的,我可以避免定义一个洞协议,并将主机设置为代理,这是一个很大的权衡。希望有帮助。

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

尚不清楚什么
操作:
选择器将导致UISplitViewController在弹出窗口中显示MasterViewController。当我最终弄明白这一点时,通过检查调试器中的
BarButtonItem
,我意识到了为什么弄明白这一点是如此棘手:苹果的iOS SDK中没有记录
操作:
选择器。哎呀

试试这个:

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

您可能希望用一个条件将此代码包围起来,以检查窗口是否处于纵向模式,例如
如果([self interfaceOrientation]==UIInterfaceOrientationGrait)

您解决了这个问题吗?我也有同样的问题。很好的解决方案,但在使用此选项后尝试旋转时崩溃了。您是以编程方式、IB还是使用故事板设置子类导航控制器?您好,Andrew,我正在使用您的解决方案“toggleMasterVisible:”并且一切正常,但当我将xcode更新为5时,它说“未声明的选择器”…那么我现在如何强制主按钮出现?
UIBarButtonItem *showListView = [[UIBarButtonItem alloc] initWithTitle:@"List" style:UIBarButtonItemStyleBordered target:[self splitViewController] action:@selector(toggleMasterVisible:)];
[[detailViewController navigationItem] setLeftBarButtonItem:showListView];