UISplitViewController的详细视图推送错误

时间:2015-06-02 15:53:37

标签: ios iphone uinavigationcontroller uinavigationbar uisplitviewcontroller

我正在使用UISplitViewController为iOS8实施通用应用,并面临UINavigation的奇怪问题,非常感谢您的专业知识。

我的项目有以下StoryBoard布局:UINavigation in UISplitViewController

在iPad上,一切都按预期工作。但是,在iPhone上运行,导航无法按预期工作。当我从"细节屏幕2"导航时,请查看此short video演示导航问题。返回"细节屏幕1"。

我尝试在一个全新的项目上实现同样的方案,但我没有看到问题。只有在移植到我现有的项目后才能看到这种行为。

更新1

这是我的AppDelegate代码:

    @interface AppDelegate () <UISplitViewControllerDelegate>

    @end

    @implementation AppDelegate

    -(BOOL) application: (UIApplication*) application didFinishLaunchingWithOptions: (NSDictionary*) launchOptions {

        UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
        UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
        navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
        splitViewController.delegate = self;

        splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;

        return YES;
    }

    #pragma mark - Split view

    - (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {

        return YES;
    }

....
@end

更新2:

感谢PetahChristian,我认为他下面的观察是正确的:

  

折叠具有导航功能的辅助视图控制器   控制器,Apple将辅助导航控制器插入到   主导航控制器的堆栈。那么,对于iPhone,你在哪里   看到问题,看起来只有一个导航   控制器,但实际上有两个。

假设观察是正确的,如何防止辅助导航控制器推入主导航控制器? UISplitViewControllerDelegate方法仅处理直接链接到UISplitViewController的辅助视图控制器的折叠逻辑。在我的情况下,要折叠的辅助视图控制器(即详细信息VC1 )通过&#34; 显示详细信息(例如替换)&#34;进行路由。来自主视图控制器的segue和UISplitViewControllerDelegate方法在此过渡期间不会执行。

在全新项目中使用完全相同的设置,Apple不会将辅助导航控制器插入主导航控制器,我也不会在新项目中遇到此问题。

非常感谢。

2 个答案:

答案 0 :(得分:2)

在我的项目中导致此导航特性的罪魁祸首是我从SO用户下载的名为ninside = 0 for xi, yi in zip(u, v): if abs(yi) < 1/np.abs(xi): ninside += 1 print(ninside) 的扩展程序。这个处理程序拦截导航后退按钮,这样当用户按下时我就有机会做额外的工作。此类别扩展代码会覆盖UIViewController+BackButtonHandler,导致默认导航中断。我不知道这个代码正在执行,因为我没有使用它,而只是在我的项目中加入。哇...把头撞到墙上2天。

答案 1 :(得分:1)

项目之间的行为不同,因为UISplitViewControllerDelegate代码不同。

新项目有必要的代码,但现有项目可能缺少它。

检查AppDelegate并比较处理折叠和分离辅助视图控制器的代码。

-splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
-splitViewController:separateSecondaryViewControllerFromPrimaryViewController:

<强>更新

你不应该在splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:中无条件地返回YES。您需要首先确定哪个视图控制器位于顶部:查看它们如何检查它是否是(辅助导航控制器及其子)详细视图控制器,并且它有详细显示?

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
    if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]] && ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
        // Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return YES;
    } else {
        return NO;
    }
}

更新2:

要折叠具有导航控制器的辅助视图控制器,Apple会将辅助导航控制器插入主导航控制器的堆栈中。所以,对于你看到问题的iPhone,它看起来只有一个导航控制器,但实际上有两个。

在你的视频中,当它看起来像你在主人,但它有一个后退按钮,然后你点击它,然后后退按钮滑出屏幕,那么辅助导航控制器就会从主要导航控制器。

为了让您的项目正常工作,您必须有条件地测试导航控制器,就像苹果一样,以确定(导航控制器及其子控件)详细视图控制器是否被丢弃。

更新3:

导航控制器本身就是一个视图控制器。它控制其子视图控制器。

辅助导航控制器辅助视图控制器。详细视图控制器是其子视图控制器。

splitView委托方法正在处理的是辅助导航控制器的崩溃或分离,辅助导航控制器碰巧有一个或多个子视图控制器。

折叠splitView控制器时,主导航控制器的堆栈看起来像[masterViewController,secondaryNavigationController]。

对于替换segue,您要替换的是Storyboard底部的Empty detail视图控制器,橙色细节屏幕1.但替换的细节视图控制器仍然有一个父级,即辅助导航控制器。当splitViewController折叠时,辅助导航控制器最终在主导航控制器堆栈上。你不会看到这个,因为它是透明的。您所看到的只是详细信息屏幕1,因为它是辅助导航控制器的顶视图控制器。

您的splitViewDelegate代码已损坏。这就是当您点按“返回”按钮时,视图控制器无法在视频中正确制作动画的原因。修复代理代码,所有查看并正常工作。

你肯定需要崩溃和单独的方法,他们需要做正确的事情。这就是为什么我建议您使用Apple的代码,而不是尝试编写自己的代码,因为Apple的代码正确地折叠并分离了导航控制器。