在 TabBarController 中显示模态视图控制器

Posted

技术标签:

【中文标题】在 TabBarController 中显示模态视图控制器【英文标题】:Present Modal ViewController via TabBarController 【发布时间】:2020-01-23 20:33:50 【问题描述】:

我有一个主要的tabBarController,并且想在点击某个tabBarItem 时显示一个viewController modally

我正在将viewControllers 加载到我的tabBarController 中...

func setupViewControllers() 
    self.tabBar.isHidden = false

    if let firstVC = storyboard?.instantiateViewController(withIdentifier: "first") as? FirstViewController, let secondVC = storyboard?.instantiateViewController(withIdentifier: "second") as? SecondViewController, let thirdVC = storyboard?.instantiateViewController(withIdentifier: "third") as? ThirdViewController, let fourthVC = storyboard?.instantiateViewController(withIdentifier: "fourth") as? FourthViewController, let fifthVC = storyboard?.instantiateViewController(withIdentifier: "fifth") as? FifthViewController 

        let firstNavController = UINavigationController(rootViewController: firstVC)
        let secondNavController = UINavigationController(rootViewController: secondVC)
        let fourthNavController = UINavigationController(rootViewController: fourthVC)
        let fifthNavController = UINavigationController(rootViewController: fifthVC)

        firstNavController.tabBarItem.image = image
        secondNavController.tabBarItem.image = image
        fourthNavController.tabBarItem.image = image
        fifthNavController.tabBarItem.image = image     
        thirdVC.tabBarItem.image = image

        tabBar.tintColor = nil

        //Load tabBar viewControllers
        viewControllers = [homeNavController, postNavController, plusMenuVC, meetupNavController, profileNavController]
    

然后我将tabBarViewControllerUITabBarControllerDelegate 一致以调用该方法...

func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool 
    if tabBarController.selectedIndex == 2, let thirdVC = viewController as? ThirdViewController 
        thirdVC.modalPresentationStyle = .overFullScreen
        thirdVC.modalTransitionStyle = .crossDissolve
        present(thirdVC, animated: true, completion: nil)
        return false
     else  return true 

然而,上述内容永远不会被触发。我尝试设置viewDidLoad

self.delegate = self

我尝试将根导航控制器及其祖先 tabBarController 委托设置为 self。

似乎没有任何工作,我希望有人可以指导我,因为我无法调试并找到现有的解决方案......

更新 所以我创建了一个dummyThirdVC 来替换setupViewControllers() 函数中的thirdVC。在dummyThirdVC 中,我符合UITabBarControllerDelegate 并在viewDidLoad 中设置self.tabBarController.delegate = self。然后我把delegate方法输入到这个dummyThirdVC中,在这个delegate方法里面,我实例化了真正的thirdVC来呈现。

delegate 方法终于正确触发了,但我现在的问题是,dummyThirdVC 及其视图必须首先加载并出现,然后才能设置和触发delegate

我怎么能不显示dummyThirdVC 并立即显示实例化的真实thirdVC?我在setupViewControllers 函数中尝试过dummyThirdVC.viewDidLoad() 无济于事......

【问题讨论】:

【参考方案1】:

我相信你的支票是错的。您正在检查 selectedIndex 是否为 2,但 selectedIndex 的值将始终是实际选项卡栏的选定索引,而不是将要选择的索引,因此您基本上永远不会到达selectedIndex 为 2。

你也不能展示一个已经处于活动状态的视图控制器,并且thirdVC 在你的tabBar 中已经处于活动状态,因此你会得到一个错误。一种解决方法是使用 viewController 作为标签栏中图像和标题的占位符,并实例化另一个用于呈现。

func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool 
    if viewController is ThirdViewController 
        let vcToPresent = storyboard?.instantiateViewController(withIdentifier: "third") as? ThirdViewController
        vcToPresent.modalPresentationStyle = .overFullScreen
        vcToPresent.modalTransitionStyle = .crossDissolve
        present(vcToPresent, animated: true, completion: nil)
        return false
    
    return true

【讨论】:

谢谢你的回答,我有两个问题。我的第一个是委托方法永远不会被触发,无论检查如何。我的第二个是我试图以模态方式呈现这个第三个 VC,而不是已经呈现的任何 VC - 如果我有这个占位符 VC 然后实例化另一个,这是一个问题吗? 1.你说你试过调试它并打印出tabBarViewController的委托,它和tabBarViewController是同一个对象吗? 2.如果您在标签栏和模态展示中使用相同的 thirdVC 实例,您将收到错误消息,因为 thirdVC 在标签栏中处于活动状态,并且您正在尝试展示已经处于活动状态的视图控制器。 问题是我在 tabBarController 的一个 rootVC 中分配了 tabBarController 委托...打印和比较对象是我发现的,呃...

以上是关于在 TabBarController 中显示模态视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式选择单元格并转到 tabbarcontroller

选项卡栏项显示具有模态序列的视图控制器

将模态视图控制器解散回嵌入在 TabBarController 中的导航控制器堆栈导致崩溃

在带有分段控件的 UITabBarController 中模态显示导航视图控制器

在 iPhone 应用程序中注销时刷新 tabbarcontroller 视图

从模态回到第一个标签栏