我正在使用UISplitViewController
为iOS8实施通用应用,并面临UINavigation
的奇怪问题,非常感谢您的专业知识。
我的项目有以下StoryBoard布局:
在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不会将辅助导航控制器插入主导航控制器,我也不会在新项目中遇到此问题。
非常感谢。
答案 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的代码正确地折叠并分离了导航控制器。