我有一个UISplitViewController,它包含一个UITabBarController作为主视图。 这个UITabBarController包含一个UINavigationController。详细视图也包含UINavigationController。
在iPad上按预期工作。 show detail segue 在详细视图上的导航控制器中显示imageview。
另一方面,在iPhone上,我预计 show detail segue 会在主视图的导航控制器的堆栈上推送详细视图。但实际上它是在主视图上以模态方式呈现的。
从故事板中删除UITabBarController并直接在主视图中使用UINavigationController时,这可以正常工作。
有人知道如何在iPhone的主人UINavigationController堆栈上呈现详细视图吗?
答案 0 :(得分:9)
彼得的解决方案的问题在于它会因iPhone 6 +而崩溃。怎么样?使用该代码,如果iPhone 6 +处于纵向 - 细节视图将推入导航堆栈。到目前为止一切都很顺利。现在,旋转到横向,然后您将详细视图显示为主视图的详细视图和。
您需要拆分视图控制器的委托来实现两种方法:
- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)detailVC sender:(id)sender
{
UITabBarController *masterVC = splitViewController.viewControllers[0];
if (splitViewController.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact)
[masterVC.selectedViewController showViewController:detailVC sender:sender];
else
[splitViewController setViewControllers:@[masterVC, detailVC]];
return YES;
}
现在,您需要从所选标签的导航控制器返回顶视图控制器:
- (UIViewController*)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController
{
UITabBarController *masterVC = splitViewController.viewControllers[0];
if ([(UINavigationController*)masterVC.selectedViewController viewControllers].count > 1)
return [(UINavigationController*)masterVC.selectedViewController popViewControllerAnimated:NO];
else
return nil; // Use the default implementation
}
使用此解决方案,一切都会在应用时推送到导航堆栈,并且还会在iPad / 6 +横向上正确更新详细视图。
答案 1 :(得分:8)
我想出了如何将详细信息放到master的UINavigationController上,而不是通过UITabBarController以模态方式呈现。
使用 UISplitViewControllerDelegate 方法
- splitViewController:showDetailViewController:sender:
如果UISplitViewController折叠,请获取主控导航控制器并将详细视图推送到此导航控制器:
- (BOOL)splitViewController:(UISplitViewController *)splitViewController
showDetailViewController:(UIViewController *)vc
sender:(id)sender {
NSLog(@"UISplitViewController collapsed: %d", splitViewController.collapsed);
// TODO: add introspection
if (splitViewController.collapsed) {
UITabBarController *master = (UITabBarController *) splitViewController.viewControllers[0];
UINavigationController *masterNavigationController = (UINavigationController *)master.selectedViewController;
// push detail view on the navigation controller
//[masterNavigationController pushViewController:vc animated:YES];
// push was not always working (see discussion in answer below), use showViewController instead
[masterNavigationController showViewController:vc sender:sender];
return YES;
}
return NO;
}
答案 2 :(得分:4)
@PeterOettl对他自己的问题的回答让我走上了正确的道路并且非常棒。所以归功于他。
我的故事板结构与他几乎相同,但由于vc
是navigationController
,我收到运行时错误
'不支持推送导航控制器'
如上所述,这是因为vc
是详细视图的navigationController
而不是详细视图的viewController。
请注意,我很惊讶@PeterOettl在他的情况下也没有得到错误,因为故事板图片中给出的segue指向详细视图的导航控制器。
因此代码应该像(在Swift中)简单地添加
let detailViewControllerNavigationController = (vc as UINavigationController).viewControllers[0] as UIViewController
并推送detailViewControllerNavigationController
而不是vc
,整个代码是
func splitViewController(splitViewController: UISplitViewController, showDetailViewController vc: UIViewController, sender: AnyObject?) -> Bool {
println("UISplitViewController collapsed: \(splitViewController.collapsed)")
if (splitViewController.collapsed) {
let master = splitViewController.viewControllers[0] as UITabBarController
let masterNavigationController = master.selectedViewController as UINavigationController
let detailViewControllerNavigationController = (vc as UINavigationController).viewControllers[0] as UIViewController
masterNavigationController.pushViewController(detailViewControllerNavigationController, animated: true)
return true
} else {
return false
}
}
另请注意,此代码放在Xcode的主 - 详细示例的AppDelegate.swift
中,其中在主视图中添加了选项卡栏。
修改强>
我们与@PeterOettl讨论了.pushViewController
和.showViewController
之间差异的评论。
Apple文档说:
showViewController:发送器:
此方法推送新的视图控制器 以类似的方式进入导航堆栈 pushViewController:animated:方法。您可以直接调用此方法 如果你想要,但通常这个方法是从其他地方调用的 在需要新视图控制器时查看控制器层次结构 所示。
适用于iOS 8.0及更高版本。
答案 3 :(得分:1)
当我实现完全相同的UI结构应用程序时,我很欣赏这个讨论主题,并且更适合iPhone 6 Plus旋转和iPad多任务处理(Slide Over / Split View,iOS 9或更高版本)。
我们已经在GitHub indievox-inc/TabBarSplitViewController上开源了完整的解决方案(自适应UISplitViewController和UITabBarController作为主视图控制器)。谢谢!
答案 4 :(得分:0)
我在Swift中实现了@Dreaming In Binary的答案:
func splitViewController(splitViewController: UISplitViewController, showDetailViewController vc: UIViewController, sender: AnyObject?) -> Bool {
let masterVC = splitViewController.viewControllers[0] as UITabBarController
if splitViewController.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact {
masterVC.selectedViewController?.showViewController(vc, sender: sender)
} else {
splitViewController.viewControllers = [masterVC, vc]
}
return true
}
func splitViewController(splitViewController: UISplitViewController, separateSecondaryViewControllerFromPrimaryViewController primaryViewController: UIViewController!) -> UIViewController? {
let masterVC = splitViewController.viewControllers[0] as UITabBarController
if let navController = masterVC.selectedViewController as? UINavigationController {
if navController.viewControllers.count > 1 {
return navController.popViewControllerAnimated(false)
}
}
return nil
}