UISplitViewController内的UITabBarController内的UINavigationController(仍然)以模态形式显示详细信息控制器,而不是按入

时间:2019-04-19 07:25:54

标签: ios swift uinavigationcontroller uitabbarcontroller uisplitviewcontroller

在通用应用程序中,我似乎有一个非常普通的设置,它的根为UISplitViewController,使用UITabBarController作为masterViewController,然后我想要:

  • 如果我在垂直iPhone上,可以将详细信息视图控制器推入堆栈中
  • 在lanscape iPhone 6+和其他较大的屏幕(如iPad等)上的UISplitViewController的detailViewController中显示详细信息控制器

为此,我的设置与所有提及类似问题的讨论中所描述的设置完全相同:

但是这些问题中提到的解决方案均无效。其中一些创建了无限递归循环和EXC_BAD_ACCESS。我尝试过的最新产品只是不断地以细节方式呈现细节视图控制器,而不是将其推入iPhone的堆栈中。我所做的是像这样创建自定义UISplitViewController子类:

    class RootSplitViewController: UISplitViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            self.delegate = self
        }
    }

    extension RootSplitViewController: UISplitViewControllerDelegate {
        func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool {
            if let tabController = splitViewController.viewControllers[0] as? UITabBarController {
                if(splitViewController.traitCollection.horizontalSizeClass == .compact) {
                    tabController.selectedViewController?.show(vc, sender: sender)
                } else {
                    splitViewController.viewControllers = [tabController, vc]
                }
            }

            return true
        }

        func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? {
            if let tabController = splitViewController.viewControllers[0] as? UITabBarController {
                if let navController = tabController.selectedViewController as? UINavigationController {
                    return navController.popViewController(animated: false)
                } else {
                    return nil
                }
            } else {
                return nil
            }
        }
    }

这是主视图控制器中用于显示详细视图控制器的代码:

self.performSegue(withIdentifier: "showReference", sender: ["tags": tags, "reference": reference])

从Firebase加载tagsreference的位置。当然,“ showReference”标记是“显示详细信息(例如替换)”。

第一个委托方法被正确调用,断点证明了这一点,当我单击UITabBarController内的列表中的某个项目时,该断点被击中。然而,细节视图控制器仍以模态显示在iPhone上。不过在iPad上没有问题:详细信息视图控制器如预期那样显示在右侧。

上面提到的大多数答案都非常老旧,并且某些解决方案是在Objective-C中实现的,所以也许我在转换中做错了什么,或者从那时起UISplitViewController实现中发生了什么改变。

有人有什么建议吗?

2 个答案:

答案 0 :(得分:2)

我知道了。实际上,它与我试图显示的目标视图控制器有关。在UISplitViewControllerDelegate中我重写的2种方法中,只有第一种被调用:

func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool {
    if let tabController = splitViewController.viewControllers[0] as? UITabBarController {
        if(splitViewController.traitCollection.horizontalSizeClass == .compact) {
            tabController.selectedViewController?.show(vc, sender: sender)
        } else {
            splitViewController.viewControllers = [tabController, vc]
        }
    }

    return true
}

但是我在测试的第一分支中显示的视图控制器已经嵌入到UINavigationController中,因此我实际上是在另一个UINavigationController中显示了UINavigationController,在这种情况下,模态更有意义。因此,在那种情况下,我需要显示extension RootSplitViewController: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool { if let tabController = splitViewController.viewControllers[0] as? UITabBarController { if(splitViewController.traitCollection.horizontalSizeClass == .compact) { if let navController = vc as? UINavigationController, let actualVc = navController.topViewController { tabController.selectedViewController?.show(actualVc, sender: sender) navController.popViewController(animated: false) } else { tabController.selectedViewController?.show(vc, sender: sender) } } else { splitViewController.viewControllers = [tabController, vc] } } return true } } 的顶视图控制器,我认为这是我在委托中重写的第二种方法的目的,但从未调用过。因此,我通过以下实现在此处完成了操作:

databaseLoader.js

这似乎在iPhone和iPad上都可以正常工作

答案 1 :(得分:0)

您尝试过ShowDetailViewController方法来更改拆分视图控制器中的详细视图控制器。

splitViewController.showDetailViewController(vc, sender: self)

如果您的视图控制器不包含导航控制器,您也可以将其嵌入到导航控制器中。

 let nav = UINavigationController.init(rootViewController: vc)
 splitViewController.showDetailViewController(nav, sender: self)