在XCode 6中,如果您基于Master-Detail应用程序模板创建一个新项目,您将获得一个适用于所有设备的通用故事板。
在主视图中选择单元时,局部视图将通过自适应的"显示详细信息"分段进行更新。在iPhone 4、5、6或6+的人像上,这段视频将按预期采取推送的形式。在横向的iPad或iPhone 6+上,它将导致详细视图按预期更新。
现在,如果您插入一个UITabBarController作为主视图控制器,该主视图控制器具有原始主视图控制器的选项卡,则在主视图中选择单元格时发生的自适应分段在iPhone上的行为与预期不一样。您现在得到的不是push转换,而是模态转换。我该怎么解决?这似乎很奇怪,默认情况下不支持。
我发现下面的帖子很有用:iOS8 TabbarController在UISplitviewController Master中但当使用建议的方法时,当我在推送人像后旋转到横向时,我在iPhone 6 Plus上的行为并不正确。细节视图的内容显示在主视图中,这并不奇怪,因为这就是建议的解决方案的作用。
谢谢!
重新观看WWDC14的视频,我想我找到了更好的答案。
- 使用自定义UISplitViewController(子类)
- 覆盖showDetailViewController操作
- 使用traitCollection确定UISplitViewController的类
- 如果水平类是Compact,则获取navigationController以调用showViewController
以下是自定义UISplitViewController的代码:
import UIKit
class CustomSplitViewController: UISplitViewController {
override func showDetailViewController(vc: UIViewController!, sender: AnyObject!) {
if (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact) {
if let tabBarController = self.viewControllers[0] as? UITabBarController {
if let navigationController = tabBarController.selectedViewController as? UINavigationController {
navigationController.showViewController(vc, sender: sender)
return
}
}
}
super.showDetailViewController(vc, sender: sender)
}
}
不要忘记在故事板中设置自定义类
在iPhone 6、iPhone 6+和iPad Air的模拟器中进行了测试,并按预期工作。
不幸的是,所选的答案对我不起作用。然而,我最终解决了这个问题:
- 子类
UISplitViewController
,并在接口生成器中设置新类 -
使新类符合
UISplitViewControllerDelegate
:required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.delegate = self }
-
实现这两种方法:
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { return true } func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool { if splitViewController.isCollapsed { guard let tabBarController = splitViewController.viewControllers.first as? UITabBarController else { return false } guard let selectedNavigationViewController = tabBarController.selectedViewController as? UINavigationController else { return false } // Push view controller var detailViewController = vc if let navController = vc as? UINavigationController, let topViewController = navController.topViewController { detailViewController = topViewController } selectedNavigationViewController.pushViewController(detailViewController, animated: true) return true } return false }
拆分控制器折叠时的docs状态,它通过调用主视图控制器上的show
来处理showDetail
,在您的情况下,主视图控制器是一个选项卡控制器。您需要将其转发到子导航控制器,如下所示:
- 制作一个选项卡控制器子类
- 在情节提要中,将选项卡控制器设置为使用新的子类
- 将此方法添加到子类中:
- (void)showViewController:(UIViewController *)vc sender:(id)sender{
[self.viewControllers.firstObject showViewController:vc sender:sender];
}
这会将其转发到第一个选项卡中的导航控制器。