当主视图控制器是UITabBarController时,自适应显示细节片段转换为模态,而不是在iPhone上推送



在XCode 6中,如果您基于Master-Detail应用程序模板创建一个新项目,您将获得一个适用于所有设备的通用故事板。

在主视图中选择单元时,局部视图将通过自适应的"显示详细信息"分段进行更新。在iPhone 4、5、6或6+的人像上,这段视频将按预期采取推送的形式。在横向的iPad或iPhone 6+上,它将导致详细视图按预期更新。

现在,如果您插入一个UITabBarController作为主视图控制器,该主视图控制器具有原始主视图控制器的选项卡,则在主视图中选择单元格时发生的自适应分段在iPhone上的行为与预期不一样。您现在得到的不是push转换,而是模态转换。我该怎么解决?这似乎很奇怪,默认情况下不支持。

我发现下面的帖子很有用:iOS8 TabbarController在UISplitviewController Master中但当使用建议的方法时,当我在推送人像后旋转到横向时,我在iPhone 6 Plus上的行为并不正确。细节视图的内容显示在主视图中,这并不奇怪,因为这就是建议的解决方案的作用。

谢谢!

重新观看WWDC14的视频,我想我找到了更好的答案。

  1. 使用自定义UISplitViewController(子类)
  2. 覆盖showDetailViewController操作
  3. 使用traitCollection确定UISplitViewController的类
  4. 如果水平类是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的模拟器中进行了测试,并按预期工作。

不幸的是,所选的答案对我不起作用。然而,我最终解决了这个问题:

  1. 子类UISplitViewController,并在接口生成器中设置新类
  2. 使新类符合UISplitViewControllerDelegate:

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
    }
    
  3. 实现这两种方法:

    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,在您的情况下,主视图控制器是一个选项卡控制器。您需要将其转发到子导航控制器,如下所示:

  1. 制作一个选项卡控制器子类
  2. 在情节提要中,将选项卡控制器设置为使用新的子类
  3. 将此方法添加到子类中:
- (void)showViewController:(UIViewController *)vc sender:(id)sender{
    [self.viewControllers.firstObject showViewController:vc sender:sender];
}

这会将其转发到第一个选项卡中的导航控制器。

最新更新