在iOS 7中,在我的第一个UITableViewController里面,我只是打电话
[self.navigationController pushViewController:otherTableVC animated:YES];
在iOS 8中:
拆分视图折叠后,其他表格变为详细视图!
然后旋转设备后,我们看到两张桌子并排…
更糟糕的是,如果设备显示两个窗格,则代码工作得很好,第二个表在主视图中被推送到第一个窗格.但是,在双轮之后,这两张桌子又是并列的.看起来UISplitViewController的折叠模式干扰我自己的导航控制器…
如何在主视图中管理我自己的UINavigationController?
谢谢
编辑:
我的主要和细节视图都有一个导航控制器.为了解决我的问题,我刚刚发现,在折叠模式下,我必须创建一个额外的导航控制器,并将其推送到主导航控制器上.
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:otherTableVC]; [self.navigationController pushViewController:navController animated:YES];
所以我只是发现了帽子,我们可以在另一个导航控制器内部导航控制器.
解决方法
splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: splitViewController:separateSecondaryViewControllerFromPrimaryViewController:
我怀疑你真正想要做的是处理你有一个基于iOS 8 UISplitViewController的应用程序的情况,其中主要和详细的视图都是UINavigationControllers,并且有一些viewControllers(在这些导航控制器中),您只想出现在分割视图的主要或细节侧.下面的答案处理这个.它也可以处理您有时希望视图更换详细信息导航控制器中的视图而不是被推送到的情况.
一个小小的注意事项:下面的代码不处理所有可能的情况,并有一些假设:
>当拆分视图折叠,并且这些视图被其上方的详细视图遮蔽时,我们不希望在“详细”导航控制器堆栈上发生任何更改.
>我们的UIViewController子类都有一个shoulddisplayInDetailedView和shouldReplaceDetailedView属性
>我们假设我们只将视图推送到具有setdisplayInDetailedView属性集的详细导航控制器上.
> View控制器通过splitViewController添加到Detail侧:showDetailViewController:或pushViewController:animated:在详细视图(以展开或折叠状态)的视图的navigationController属性上.
>只能在Detail导览控制器中替换视图控制器的View控制器只能通过splitViewController:showDetailViewController进行添加:仅在主视图控制器中与视图进行交互,即只有当主视图控制器在崩溃状态
>当分割视图控制器被扩展时,我们有一个BlankViewController显示在Detail View中,但是我们只有一个应该保留在Primary侧的视图控制器.
我不建议仅执行splitViewController的一侧:collapseSecondaryViewController:toPrimaryViewController:/ splitViewController:separateSecondaryViewControllerFromPrimaryViewController:逻辑,并取决于另一方的默认实现.苹果做一些奇怪的事情,如把UINavigationViewController从细节方面放到主要的一面,作为主导航控制器堆栈中的一个viewController,然后推送其上的其他视图控制器,即使您完全理解仍然无法复制你自己的代码因此,最好自己处理这个过程的双方.
这是我用的:
#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;
}