【问题标题】:Adaptive show detail segue transformed to modal instead of push on iPhone when master view controller is a UITabBarController当主视图控制器是 UITabBarController 时,自适应显示细节 segue 转换为模式而不是在 iPhone 上推送
【发布时间】:2014-11-30 02:23:02
【问题描述】:

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

在主视图中选择单元格时,详细视图会通过自适应“显示详细信息”转场进行更新。在 iPhone 4、5、6 或 6+ 的纵向上,这种转场将按预期采用推送的形式。在 iPad 或 iPhone 6+ 的横向上,它将导致详细视图按预期更新。

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

我发现以下帖子很有用:iOS8 TabbarController inside a UISplitviewController Master 但是当使用建议的方法时,当我在按下纵向后旋转到横向时,我在 iPhone 6 Plus 上没有得到正确的行为。详细视图的内容出现在主视图中,这并不奇怪,因为建议的解决方案就是这样做的。

谢谢!

【问题讨论】:

  • 原来的主视图控制器是否嵌入了导航控制器(所以选项卡的根视图控制器就是导航控制器)?
  • 是的,标签的根视图控制器是一个导航控制器,而导航控制器又包含一个表格视图控制器。

标签: ios iphone


【解决方案1】:

重看 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 的模拟器中测试并按预期工作。

【讨论】:

  • 您的解决方案完美运行。非常感谢。请注意,我还必须修改默认的 separateSecondaryViewControllerFromPrimaryViewController 和 collapseSecondaryViewController 方法以获得我需要的行为。
  • @phamel 你能分享一下你在这种情况下最终不得不做的代码修改吗?
  • 拆分控制器为您完成所有这些工作。只需子类化选项卡控制器并覆盖显示并将其转发到子导航控制器。
【解决方案2】:

很遗憾,所选答案对我不起作用。不过,我最终还是设法解决了这个问题:

  1. 子类 UISplitViewController 并在 Interface Builder 中设置新类。
  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
    }
    

【讨论】:

  • 永远不要将委托设置为自己。创建一个控制器类。
【解决方案3】:

拆分控制器折叠时的文档状态,它通过在主视图控制器上调用 show 来处理 showDetail,在您的情况下,主视图控制器是一个选项卡控制器。您需要将其转发到子导航控制器,如下所示:

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

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

【讨论】:

  • 我正在尝试,但我得到一个 EXC_BAD_ACCESS 因为它似乎调用显示是递归的。你能显示一些代码吗?
  • 我猜你在标签控制器子类中不小心调用了 super showViewController。没有任何代码可以显示,但我会添加更多步骤。
猜你喜欢
  • 2013-01-19
  • 2019-09-09
  • 2012-01-16
  • 1970-01-01
  • 2017-12-20
  • 2020-12-15
  • 2016-03-31
  • 1970-01-01
  • 2017-12-11
相关资源
最近更新 更多