在iOS 8中的UISplitViewController的主视图中有一个UINavigationController [英] Having a UINavigationController in the master view of a UISplitViewController in iOS 8

查看:174
本文介绍了在iOS 8中的UISplitViewController的主视图中有一个UINavigationController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的UISplitViewController中,主视图是一个包含UITableViewController的UINavigationController。有时,当用户选择表中的项时,我必须在主视图中的现有表上推送另一个tableViewController。

In my UISplitViewController, the master view is a UINavigationController containing a UITableViewController. Sometime, when the user selects an item in the table, I have to push another tableViewController over the existing table in the master view.

在iOS 7中,在我的第一个UITableViewController中我只是打电话

In iOS 7, inside my first UITableViewController I just call

[self.navigationController pushViewController:otherTableVC animated:YES];

在iOS 8中:

当拆分视图折叠后,otherTableVC成为详细视图!
然后在旋转设备后,我们并排看到两个表...

When the split view is collapsed, the otherTableVC becomes the detail View! Then after rotating the device, we see the two tables side by side...

更糟糕的是,如果设备显示两个窗格,代码效果很好并且第二个表被推到主视图中的第一个表上。但是,经过两次旋转后,两张桌子又是并排的。似乎UISplitViewController的折叠模式干扰了我自己的导航控制器...

Worse, if the device shows the two panes, the code works great and the second table is pushed over the first one in the master view. But, after a double rotation, the two tables are again side by side. It seems the collapsed mode of the UISplitViewController interferes with my own navigation controller...

如何在主视图中管理我自己的UINavigationController?

How can I manage my own UINavigationController in the Master View?

谢谢

已编辑:

我的主视图和详细信息视图都有一个导航控制器。为了解决我的问题,我刚刚发现,在折叠模式下,我必须创建一个额外的导航控制器并将其推到主导航控制器上。

My both primary and details views have a navigation Controller. And to solve my problem, I just discovered that, in collapsed mode, I have to create an extra Navigation Controller and push it over the primary navigation controller.

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:otherTableVC];
[self.navigationController pushViewController:navController animated:YES];

所以我发现帽子我们可以将导航控制器推到另一个导航控制器内。

So I just discovered hat we can push a navigation Controller inside another Navigation Controller.

推荐答案

简短的回答,您可以通过UISplitViewControllerDelegate方法控制此行为:

Short answer, you can control this behaviour via the UISplitViewControllerDelegate methods:

splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
splitViewController:separateSecondaryViewControllerFromPrimaryViewController:

我怀疑你真正想做的是处理你有一个基于iOS 8 UISplitViewController的应用程序的情况,你的主要和详细视图都是UINavigationControllers,并且你想要只出现一些viewControllers(在这些导航控制器中)拆分视图的主要部分或细节部分。以下答案涉及此问题。它还可以处理你有时希望视图替换Detail导航控制器中的视图而不是被推到那里的情况。

I suspect what you really want to do is deal with the situation where you have an iOS 8 UISplitViewController-based app where your primary and detailed views are both UINavigationControllers and there are some viewControllers (within these navigation controllers) that you want to appear only on the primary or detail side of the split view. The answer below deals with this. It also copes with the situation where you sometimes wish for a view to replace the views in the Detail navigation controller, rather than getting pushed there.

一个小警告:代码下面没有涉及所有可能的情况并且有一些假设:

A small caveat: the code below does not deal with all possible cases and has some assumptions:


  • 我们预计在详细的导航控制器堆栈上什么都不会改变拆分视图已折叠,这些视图被上面的详细视图遮挡。

  • 我们的UIViewController子类都有一个shouldDisplayInDetailedView和shouldReplaceDetailedView属性

  • 我们假设我们只将视图推送到具有shouldDisplayInDetailedView属性集的详细导航控制器。

  • 通过splitViewController将视图控制器添加到Detail端:showDetailViewController:或pushViewController:animated:on详细视图中的视图的navigationController属性(处于展开或折叠状态)。

  • 只能通过splitViewController:showDetailViewController添加替换详细信息导航控制器中视图控制器的控制器,并且只能从主视图控制器中的视图交互中添加,即只有在处于折叠状态时主视图控制器未被遮挡时才会发生这种情况。

  • 当拆分视图控制器扩展但我们有详细视图中显示的BlankViewController时只有视图控制器应保留在主端。

  • We don't expect anything can change on the Detailed navigation controller stack when the split view is collapsed and those views are obscured by a detailed view above them.
  • Our UIViewController subclasses all have a shouldDisplayInDetailedView and shouldReplaceDetailedView property
  • We assume that we only push views onto the detailed navigation controller that have the shouldDisplayInDetailedView property set.
  • View controllers are added to the Detail side via splitViewController:showDetailViewController: or a pushViewController:animated: on the navigationController property of a view within a detailed view (in either expanded or collapsed state).
  • View controllers that should replace the view controllers in the Detail navigation controller are only added via splitViewController:showDetailViewController: and only from interaction with view in the Primary view controller, i.e., this can only happen if the Primary view controller is not obscured when in collapsed state.
  • We have a BlankViewController to display in the Detail View when the split view controller gets expanded but we only have view controllers that should stay on the Primary side.

我不建议只实现splitViewController的一面:collapseSecondaryViewController: ontoPrimaryViewController:/ splitViewController:separateSecondaryViewControllerFromPrimaryViewController:逻辑并取决于另一方的默认实现。 Apple做了一些奇怪的事情,比如将UINavigationViewController从Detail端放入主要侧作为Primary导航控制器堆栈中的一个viewControllers,然后推送其上方的其他视图控制器,即使你完全理解仍然无法复制你自己的代码。因此,最好自己处理这两个过程。

I don't recommend implementing only one side of the splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: / splitViewController: separateSecondaryViewControllerFromPrimaryViewController: logic and depending on the default implementation for the other side. Apple do some strange things like putting the UINavigationViewController from the Detail side into the primary side as one of the viewControllers in the Primary navigation controller stack but then pushing other view controllers above it, which even if you understand completely still can't be replicated from your own code. Thus its best to handle both sides of the process yourself.

这就是我使用的:

#pragma mark -
#pragma mark Split View Controller delegate.

- (BOOL)splitViewController:(UISplitViewController *)splitViewController showViewController:(UIViewController *)vc sender:(id)sender
{
    //Standard behaviour.  This won't get called in our case when the split view is collapsed and the primary view controllers are obscured.
    return NO;
}

// Since we treat warnings as errors, silence warning about unknown selector below on UIViewController subclasses.
#pragma GCC diagnostic ignored "-Wundeclared-selector"


- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(id)sender
{
    if (splitViewController.collapsed == NO)
    {
        // The navigation controller we'll be adding the view controller vc to.
        UINavigationController *navController = splitViewController.viewControllers[1];

        UIViewController *topDetailViewController = [navController.viewControllers lastObject];
        if ([topDetailViewController isKindOfClass:[BlankViewController class]] ||
           ([vc respondsToSelector:@selector(shouldReplaceDetailedView)] && [vc performSelector:@selector(shouldReplaceDetailedView)]))
        {
            // Replace the (expanded) detail view with this new view controller.
            [navController setViewControllers:@[vc] animated:NO];
        }
        else
        {
            // Otherwise, just push.
            [navController pushViewController:vc animated:YES];
        }
    }
    else
    {
        // Collapsed.  Just push onto the conbined primary and detailed navigation controller.
        UINavigationController *navController = splitViewController.viewControllers[0];
        [navController pushViewController:vc animated:YES];
    }

    // We've handled this ourselves.
    return YES;
}

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController
{
    UINavigationController *primaryNavController = (UINavigationController *)primaryViewController;
    UINavigationController *secondaryNavController = (UINavigationController *)secondaryViewController;
    UIViewController *bottomSecondaryView = [secondaryNavController.viewControllers firstObject];
    if ([bottomSecondaryView isKindOfClass:[BlankViewController class]])
    {
        NSAssert([secondaryNavController.viewControllers count] == 1, @"BlankViewController is not only detail view controller");
        // If our secondary controller is blank, do the collapse ourself by doing nothing.
        return YES;
    }

    // We need to shift these view controllers ourselves.
    // This should be the primary views and then the detailed views on top.
    // Otherwise the UISplitViewController does wacky things like embedding a UINavigationController inside another UINavigation Controller, which causes problems for us later.
    NSMutableArray *newPrimaryViewControllers = [NSMutableArray arrayWithArray:primaryNavController.viewControllers];
    [newPrimaryViewControllers addObjectsFromArray:secondaryNavController.viewControllers];
    primaryNavController.viewControllers = newPrimaryViewControllers;

    return YES;
}

- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController
{
    UINavigationController *primaryNavController = (UINavigationController *)primaryViewController;

    // Split up the combined primary and detail navigation controller in their component primary and detail view controller lists, but with same ordering.
    NSMutableArray *newPrimaryViewControllers = [NSMutableArray array];
    NSMutableArray *newDetailViewControllers = [NSMutableArray array];
    for (UIViewController *controller in primaryNavController.viewControllers)
    {
        if ([controller respondsToSelector:@selector(shouldDisplayInDetailedView)] && [controller performSelector:@selector(shouldDisplayInDetailedView)])
        {
            [newDetailViewControllers addObject:controller];
        }
        else
        {
            [newPrimaryViewControllers addObject:controller];
        }
    }

    if (newDetailViewControllers.count == 0)
    {
        // If there's no detailed views on the top of the navigation stack, return a blank view  (in navigation controller) for detailed side.
        UINavigationController *blankDetailNavController = [[UINavigationController alloc] initWithRootViewController:[[BlankViewController alloc] init]];
        return blankDetailNavController;
    }

    // Set the new primary views.
    primaryNavController.viewControllers = newPrimaryViewControllers;

    // Return the new detail navigation controller and views.
    UINavigationController *detailNavController = [[UINavigationController alloc] init];
    detailNavController.viewControllers = newDetailViewControllers;
    return detailNavController;
}

这篇关于在iOS 8中的UISplitViewController的主视图中有一个UINavigationController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆