简体   繁体   English

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

[英]iOS UISplitViewController's Popover controller button disappear after pushing new view controller in portrait mode

In my UISplitViewController application, I have 在我的UISplitViewController应用程序中,我有

  • RootViewController - view controller in the left pane. RootViewController - 左窗格中的视图控制器。
  • DetailViewController - view controller in the right pane. DetailViewController - 右窗格中的视图控制器。

When one item (which is in a UITableView) in RootViewController is tapped, new view controller will be set as the following shows: 当点击RootViewController中的一个项目(在UITableView中)时,将设置新的视图控制器,如下所示:

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

//detailPane is my DetailViewController

All works pretty well in landscape mode. 一切都在横向模式下很好用。 However, I can't make the UISplitViewController work as what I want in portrait mode, that is, the RootViewController's popover button does not appear appropriately in my DetailViewController when I launch and use the application in portait mode. 但是,我无法使UISplitViewController在纵向模式下工作,也就是说,当我在portait模式下启动并使用应用程序时,RootViewController的弹出按钮在我的DetailViewController中没有正确显示。

When I launch the app in portrait mode, the popover button appears appropriately. 当我以纵向模式启动应用程序时,弹出按钮会正确显示。 But after tapping one item in the popover and a new view controller has been set on detailViewController, the button disappeared. 但是在弹出窗口中的一个项目并且在detailViewController上设置了新的视图控制器之后,该按钮消失了。 I have to rotate the device to landscape and then back to portrait again to make the button appear again. 我必须将设备旋转到横向,然后再次回到纵向以使按钮再次出现。

I set my UISplitViewController's delegate in my application's AppDelegate as follows: 我在我的应用程序的AppDelegate中设置了我的UISplitViewController的委托,如下所示:

self.splitViewController.delegate = self.detailViewController

And here is my UISplitViewControllerDelegate implementation 这是我的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;   
}

Any hint or help is greatly appreciated. 非常感谢任何提示或帮助。 Thanks. 谢谢。

Just came up with a new solution. 刚刚提出了一个新的解决方案。

Subclass UINavigationController and implement UISplitViewControllerDelegate . 子类UINavigationController并实现UISplitViewControllerDelegate Set an instance of this class as the right ViewController of the splitViewController. 将此类的实例设置为splitViewController的右侧ViewController。 Everytime you want to change the detail view controller from the master 每次要从主服务器更改详细视图控制器时

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

This works for me and I can avoid defining a hole protocol and setting the master as the delegate, which is a big trade off. 这对我有用,我可以避免定义一个空洞协议并将主设置为委托,这是一个很大的权衡。 Hope it helps. 希望能帮助到你。

If you still need it: 如果你还需要它:

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

What I did to my source (I had similar setup to you) to fix it: 我对我的来源做了什么(我有类似的设置)来解决它:

I have the master viewcontroller (UITableViewController in my case) be the delegate of the UISplitViewController. 我有主视图控制器(在我的情况下是UITableViewController)是UISplitViewController的委托。 In the two delegate methods for UISplitViewControllers (so this would be in your master viewcontroller implementation) you would save the popupviewcontroller and the barbuttonitem in your class. 在UISplitViewControllers的两个委托方法中(因此这将在您的主视图控制器实现中),您将在类中保存popupviewcontroller和barbuttonitem。 Now, if you change your details viewcontroller, you do: 现在,如果您更改详细信息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];

where we have 我们在哪里

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

the delegate that each of your detailsViewControllers should adhere to. 每个您的detailsViewControllers应遵守的委托。 You would implement like this: 你会这样实现:

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

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

Let me know if this helps you. 如果这有助于您,请告诉我。

I liked Nekto's solution, but it misses one key problem. 我喜欢Nekto的解决方案,但它错过了一个关键问题。

It's not clear what action: selector will cause the UISplitViewController to show the MasterViewController in a popover. 目前尚不清楚是什么action:选择器将导致UISplitViewController在弹出窗口中显示MasterViewController。 When I finally figured this out, by examining the BarButtonItem in the debugger, I realized why it was so tricky to figure this out: the action: selector isn't documented anywhere in Apple's iOS SDK. 当我最终弄清楚这一点时,通过检查调试器中的BarButtonItem ,我意识到为什么解决这个问题是如此棘手: action:选择器没有记录在Apple的iOS SDK中。 Oops. 哎呀。

Try this: 尝试这个:

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

You may want to surround this code with a conditional that checks the window is in in portrait mode, such as if ([self interfaceOrientation] == UIInterfaceOrientationPortrait) 您可能希望使用检查窗口处于纵向模式的条件来包围此代码,例如if ([self interfaceOrientation] == UIInterfaceOrientationPortrait)

When you are setting new view controllers placed on navigation stack , probably, all navigation buttons are reset. 当您设置放置在navigation stack上的新视图控制器时,可能会重置所有导航按钮。 You can manually add appropriate buttons after changing navigation stack . 您可以在更改navigation stack后手动添加适当的按钮。

For example, you can pick code from - (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc where default popover controller button is created: 例如,您可以从- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc选择代码- (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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM