在我的通用应用程序中,我有一个似乎非常常见的设置,具有根 UISplitViewController,使用 UITabBarController 作为 masterViewController ,然后我想:
UISplitViewController 的 detailViewController 中显示细节 Controller 为此,我的设置与所有提到类似问题的讨论中描述的设置完全相同:
但这些问题中提到的解决方案均无效。其中一些创建无限递归循环和 EXC_BAD_ACCESS。我尝试的最新方法只是简单地以模态方式呈现细节 View Controller ,而不是将其推送到 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
}
}
}
下面是主视图 Controller 中显示详细 View Controller 的代码:
self.performSegue(withIdentifier: "showReference", sender: ["tags": tags, "reference": reference])
从 Firebase 加载的 tags 和 reference 在哪里。当然,“showReference”转场属于“显示详细信息(例如替换)”类型。
第一个委托(delegate)方法被正确调用,当我在 UITabBarController 中单击列表中的项目时,断点就证明了这一点。然而细节 View Controller 仍然以模态方式呈现在 iPhone 上。不过在 iPad 上没问题:细节 View Controller 出现在右侧,正如预期的那样。
上面提到的大多数答案都非常陈旧,一些解决方案是在 Objective-C 中实现的,所以可能我在转换中做错了什么,或者从那时起 UISplitViewController 实现中发生了一些变化。
有人有什么建议吗?
最佳答案
我想通了。事实上,它与我试图展示的目标 View Controller 有关。在 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
}
但我在测试的第一个分支中显示的 View Controller 已经嵌入到 UINavigationController 中,所以我实际上是在将 UINavigationController 显示到另一个中,并且在那种情况下,模式更有意义。所以在这种情况下,我需要显示 UINavigationController 的顶 View Controller ,我认为这是我在委托(delegate)中重写的第二个方法的目的,但它从未被调用过。所以我通过以下实现就在那里做到了:
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
}
}
这似乎在 iPhone 和 iPad 上都能完美运行
关于ios - UINavigationController inside UITabBarController inside UISplitViewController(仍然)以模态方式显示细节 Controller 而不是推送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55758146/