UINavigationController inside UITabBarController inside UISplitViewController(仍然)以模态方式显示细节控制器而不是推送
UINavigationController inside UITabBarController inside UISplitViewController (still) shows detail controller modally instead of pushing
我的通用应用程序中有一个似乎非常常见的设置,根 UISplitViewController
,使用 UITabBarController
作为 masterViewController
,然后我想:
- 如果我在垂直方向上,要么将详细视图控制器推入堆栈 iPhone
- 在横向 iPhone 6+ 和 iPads 等
等更大屏幕上的 UISplitViewController
的 detailViewController 中显示细节控制器
为此,我的设置与所有提到类似问题的讨论中描述的设置完全相同:
- UINavigationController inside a UITabBarController inside a UISplitViewController presented modally on iPhone
- iOS8 TabbarController inside a UISplitviewController Master
- Adaptive show detail segue transformed to modal instead of push on iPhone when master view controller is a UITabBarController
但是这些问题中提到的 none 解决方案有效。其中一些创建了一个无限递归循环和一个 EXC_BAD_ACCESS
。我尝试的最新一个只是简单地以模态方式呈现细节视图控制器,而不是在 iPhones 上将其推入堆栈。我所做的是创建一个自定义 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])
其中 tags
和 reference
从 Firebase 加载。当然 "showReference" segue 属于 "Show Detail (e.g. Replace)" 类型。
第一个委托方法被正确调用,当我单击 UITabBarController
中的列表中的项目时,断点就证明了这一点。然而细节视图控制器仍然以模态方式呈现在 iPhone 上。不过 iPad 没问题:细节视图控制器出现在右侧,正如预期的那样。
上面提到的大多数答案都已经很老了,一些解决方案是在 Objective-C 中实现的,所以也许我在转换中做错了什么,或者从那时起在 UISplitViewController
实现中发生了一些变化.
有人有什么建议吗?
您是否尝试过 ShowDetailViewController 方法来更改拆分视图控制器中的详细视图控制器。
splitViewController.showDetailViewController(vc, sender: self)
如果您的视图控制器不包含导航控制器,您也可以将其嵌入到导航控制器中。
let nav = UINavigationController.init(rootViewController: vc)
splitViewController.showDetailViewController(nav, sender: self)
我明白了。事实上,它与我试图展示的目标视图控制器有关。在 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
}
}
这似乎在 iPhone 和 iPad 上都能完美运行
我的通用应用程序中有一个似乎非常常见的设置,根 UISplitViewController
,使用 UITabBarController
作为 masterViewController
,然后我想:
- 如果我在垂直方向上,要么将详细视图控制器推入堆栈 iPhone
- 在横向 iPhone 6+ 和 iPads 等 等更大屏幕上的
UISplitViewController
的 detailViewController 中显示细节控制器
为此,我的设置与所有提到类似问题的讨论中描述的设置完全相同:
- UINavigationController inside a UITabBarController inside a UISplitViewController presented modally on iPhone
- iOS8 TabbarController inside a UISplitviewController Master
- Adaptive show detail segue transformed to modal instead of push on iPhone when master view controller is a UITabBarController
但是这些问题中提到的 none 解决方案有效。其中一些创建了一个无限递归循环和一个 EXC_BAD_ACCESS
。我尝试的最新一个只是简单地以模态方式呈现细节视图控制器,而不是在 iPhones 上将其推入堆栈。我所做的是创建一个自定义 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])
其中 tags
和 reference
从 Firebase 加载。当然 "showReference" segue 属于 "Show Detail (e.g. Replace)" 类型。
第一个委托方法被正确调用,当我单击 UITabBarController
中的列表中的项目时,断点就证明了这一点。然而细节视图控制器仍然以模态方式呈现在 iPhone 上。不过 iPad 没问题:细节视图控制器出现在右侧,正如预期的那样。
上面提到的大多数答案都已经很老了,一些解决方案是在 Objective-C 中实现的,所以也许我在转换中做错了什么,或者从那时起在 UISplitViewController
实现中发生了一些变化.
有人有什么建议吗?
您是否尝试过 ShowDetailViewController 方法来更改拆分视图控制器中的详细视图控制器。
splitViewController.showDetailViewController(vc, sender: self)
如果您的视图控制器不包含导航控制器,您也可以将其嵌入到导航控制器中。
let nav = UINavigationController.init(rootViewController: vc)
splitViewController.showDetailViewController(nav, sender: self)
我明白了。事实上,它与我试图展示的目标视图控制器有关。在 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
}
}
这似乎在 iPhone 和 iPad 上都能完美运行