使用标签栏和导航实例化深度视图控制器

Posted

技术标签:

【中文标题】使用标签栏和导航实例化深度视图控制器【英文标题】:Instantiating deep View Controller with Tab bar and Navigation 【发布时间】:2019-10-08 14:26:18 【问题描述】:

我正在使用 Xcode 11 和 Swift 5。

收到 APNS 通知后,我需要从 AppDelegate 跳转到故事板深处的视图控制器。这个 viewController (chatVC) 位于标签栏和导航控制器以及其他几个视图控制器的后面。见下图。我知道如何检查标签通知以及如何在 AppDelegate 中使用 launchOptions 来触发跳转。但是我正在为如何为最后一个视图控制器建立上下文而苦苦挣扎,以便用户可以使用后退按钮一直返回标签栏控制器。

我已经阅读了许多 SO 答案,并尝试了许多方法,但似乎没有一个在选项卡栏控制器内具有相同的导航控制器嵌入。这是我在 AppDelegate 中的代码(在阅读通知中的标签后):

        if tag == "CS" 
            // Set up a Chat View Controller.
            if let chatVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.chatVC) as? NewChatViewController,
                let tabBarVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.tabBarController) as? UITabBarController,
                let csVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.csViewController) as? CustomerServiceViewController,
                let helpVC = UIStoryboard(name:"Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.helpVC) as? HelpViewController
            
                // Set the customer service document Id.
                chatVC.cs = cs
                // Make the tabBarVC the Root View Controller
                self.window?.rootViewController = tabBarVC
                self.window?.makeKeyAndVisible()
                // Select the Favorites Index.
                tabBarVC.selectedIndex = 0
                // Push the Customer Service VC on top.
                tabBarVC.show(csVC, sender: Any?.self)
                // Push the Help VC on top of Customer Service VC.
                csVC.show(helpVC, sender: Any?.self)
                // Push the the chat detail page on top.
                helpVC.show(chatVC, sender: Any?.self)
            
        
    
    return true

如何跳转到 chatVC 并在其下方设置导航上下文以便可以使用后退按钮?

【问题讨论】:

【参考方案1】:

你可以这样做:

guard let tabBarVC = UIApplication.shared.windows.filter( $0.rootViewController is UITabBarController  ).first?.rootViewController as? UITabBarController else  return 
tabBarVC.selectedIndex = 0 //you can select another tab if needed
guard let chatVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.chatVC) as? NewChatViewController else  return 
if let navController = tabBarVC.viewControllers?[0] as? UINavigationController 
   navController.pushViewController(chatVC, animated: true)

您还可以在推送通知之前将通知中的对象传递给您的chatVC,以备不时之需。

希望这对你有用!

【讨论】:

谢谢。我会尝试并报告。 效果很好。请注意,我将 return 更改为 return true ,因为我在 AppDelegate 中。为了我自己的学习,请问我设置tabBarVC和使用window?.rootViewController = tabBarVC的代码和你使用let tabBarVC = UIApplication.shared.windows.filter ...的代码之间是否有区别?看来关键在if let navController = tabBarVC.viewControllers?[0] ... 我很欣赏你优雅而有效的代码! 实际上,您的做法也是正确的,但前提是应用程序是从通知启动的。如果用户已经在应用程序内部并且您发送通知,并且您想要处理该通知(显示警报、横幅等),那么您将需要使用我的代码,否则您将释放已经存在的 tabBar使用所有视图控制器,并将其替换为 tabBarVC 的新实例。 知道了。我刚刚在编写应用程序打开的情况。所以这是完美的时机。再次感谢!

以上是关于使用标签栏和导航实例化深度视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

标签栏和导航控制器在视图控制器中看不到了

如何使用 swift 在子视图中添加标签栏和导航栏?

组合标签栏和导航栏控制器出现问题

如何在视图控制器中的标签栏和导航栏上全屏显示弹出视图?

呈现一个导航栏和一个非根视图标签栏控制器

iOS MapView 位于导航栏、状态栏和标签栏控制器下