UISplitViewController - 使用UINavigationController的多个详细信息视图

时间:2012-02-14 13:20:26

标签: ios uinavigationcontroller uisplitviewcontroller

我正在将iPhone应用程序转换为通用应用程序,并且将嵌套表转换为UISplitViewController配置大部分都是直接的,但是在iPad上运行时我仍有一个问题让我头疼。

对于通用应用程序兼容性,“主”视图包含一个UINavigationController,用于浏览每个显示菜单的一系列TableView。这很好。

最终,用户到达详细视图中显示的内容。每个细节视图'链'都包含在UINavigationController中,因为一些视图可以向下钻取以显示地图等。想法是弹出按钮将位于详细视图的根级别。值得注意的是,每次选择该行时都会从头开始创建详细视图。

我研究过Apple的多重详细信息视图Sample Code,因此使用主视图作为UISplitViewController委托,它提供了隐藏/显示弹出窗口选择器,然后将调用传递给选择的任何替代详细信息视图

在横向模式下工作时,我可以在主视图中选择不同的行,并且详细视图可以很好地切换 - 一切都很好。太棒了。

在纵向模式下,事情不能很好地工作......当旋转到肖像时,弹出按钮在当前选定的细节视图中正确显示,但是当选择了一行时(即它以某种方式未正确添加),它会消失到新选择的视图的NavBar)。

我添加了诊断代码,看起来正在进行正确的调用(使用正确的指针)以在新选择的详细信息视图上显示弹出框。此外,我可以旋转到横向并再次返回,然后出现弹出按钮,所以我很合理地认为popover UIBarButtonItem正确地连接到新的细节NavBar。

由于在选择行之前未创建详细视图,我想知道这是否是在调用showRootPopoverButtonItem时未实例化UINavigationBar的情况(基于Apple的示例代码)。如果我旋转到横向并再次返回(如上所述)并选择相同的视图,则会出现弹出按钮的事实,这一理论得到了支持。

我也在Apple的示例代码中看到了这条评论,在didSelectRowAtIndexPath中,在切换详细视图之前,请注意使用“after”一词......

// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).

所以,我尝试在viewWillAppear中再次调用showRootPopoverButton方法(此时UINavigationBar应该存在),但这不会导致弹出窗口按钮出现。

我很欣赏在纵向模式下从主视图中选择新行时如何立即显示弹出框的任何想法和建议。感谢。

感谢您阅读此内容,相关代码如下所示。

从主视图,这里是UISplitViewControllerDelegate选择器,

- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc
{

    // Keep references to the popover controller and the popover button, and tell the detail view controller to show the button.
    barButtonItem.title = @"Root View Controller";
    self.popoverController = pc;
    self.rootPopoverButtonItem = barButtonItem;
    //UIViewController <SubstitutableDetailViewController> *detailViewController = [self.splitViewController.viewControllers objectAtIndex:1];

    // ^ Apple's example, commented out, my equivalent code to obtain
    // active detail navigation controller below,

    UINavigationController *detailNavController = [self.splitViewController.viewControllers objectAtIndex:1];
    UIViewController *detailViewController = detailNavController.visibleViewController;

    [detailViewController showRootPopoverButtonItem:rootPopoverButtonItem];
}


- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
     // Nil out references to the popover controller and the popover button, and tell the detail view controller to hide the button.
     UINavigationController *detailNavController = [self.splitViewController.viewControllers objectAtIndex:1];
     UIViewController *detailViewController = detailNavController.visibleViewController;
     [detailViewController invalidateRootPopoverButtonItem:rootPopoverButtonItem];
     self.popoverController = nil;
     self.rootPopoverButtonItem = nil;
}

而且,非常像Apple的例子,这是在主表中选择行时会发生什么,

if (rootPopoverButtonItem != nil)
{
    NSLog (@"show popover button");
    [newDetailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}

从详细视图中,

- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem
{
    NSLog (@"detailViewController (view: %p, button: %p, nav: %p): showRootPopoverButton", self, barButtonItem, self.navigationItem);

    barButtonItem.title = self.navigationItem.title;

    [self.navigationItem setLeftBarButtonItem:barButtonItem animated:NO];

    popoverButton = barButtonItem;
}


- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem
{    
    NSLog (@"detailViewController (%p): invalidateRootPopoverButton", self);

    // Called when the view is shown again in the split view, invalidating the button and popover controller.
    [self.navigationItem setLeftBarButtonItem:nil animated:NO];

    popoverButton = nil;
}

1 个答案:

答案 0 :(得分:3)

我认为有两件事可能是问题所在。您应该包含其余代码。特别是当用户在主服务器中执行操作时更改详细视图控制器的部分。

    如果您刚刚实例化visibleViewController,则
  1. detailNavController可能为零。即使你设置它的根,也没有“可见”的视图控制器,因为它实际上还没有显示。您可以尝试使用topViewController

  2. 我不确定每次用户在主人中选择某些内容时是否要创建新的detailNavController,但如果您是,则需要将rootPopoverButtonItem传递给{ {1}},因为只有在方向发生变化时才会自动调用detailViewController