如何创建以 TabBarViewController 为根的导航堆栈?

Posted

技术标签:

【中文标题】如何创建以 TabBarViewController 为根的导航堆栈?【英文标题】:How can I create a navigation stack with TabBarViewController as the root? 【发布时间】:2016-02-15 02:29:22 【问题描述】:

我的 TabBarVC 是我的应用程序的核心。我有 3 个视图控制器。每个视图控制器都“嵌入”在导航控制器中。

TabBarVC -> UINavigationController -> HomeVC
         -> UINavigationController -> TimelineVC
         -> UINavigationController -> ConversationVC

我希望我的TabBarVC 能够随时将InstantMessageViewController 推送到它的堆栈上。我知道 TabBarVC 没有“堆栈”或 NavigationController - 只有它的子级才有导航控制器。

TabBarVC 收到NSNotification 时,我想将InstantMessageViewController 推入其堆栈。

TabBarVC 里面可能有这样的东西?

let mvc = self?.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! InstantMessagesViewController
mvc.user = self?.notificationUser
self?.navigationController?.pushViewController(mvc, animated: true) //it doens't work because self.navigationController is nil.

当用户按下返回按钮时,它会返回到 TabBarVC。

我希望能够随时将多个InstantMessagesViewController 推入堆栈并以编程方式重新排序。

我不知道什么是最好的方法。我要创建一个 UIWINdow 吗?我是否以编程方式创建 UINavigationController?

【问题讨论】:

【参考方案1】:

您可以做的一件事是将InstantMessagesViewController 推送到当前在UITabBarController 上选择的UINavigationController

// Inside your UITabBarController
if let navigationController = selectedViewController 
    let mvc = self?.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! InstantMessagesViewController
    mvc.user = self?.notificationUser
    navigationController.pushViewController(mvc, animated: true)

但正确的做法是以模态方式呈现InstantMessagesViewController(并将您随后的InstantMessagesViewControllers 推入此UINavigationController 堆栈):

let mvc = self?.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! InstantMessagesViewController
mvc.user = self?.notificationUser
let navController = UINavigationController(rootViewController: mvc)
presentViewController(navController, animated: true, completion: nil)

要在您的根目录InstantMessagesViewController 上关闭此UINavigationController,请在InstantMessagesViewController 中尝试以下代码:

override func viewDidLoad() 
    super.viewDidLoad()

    if let navigationController = navigationController 
        if navigationController.viewControllers.count == 1 
            let barButton = UIBarButtonItem(title: "Back", style: .Plain, target: self, action: "onBackTapped:")
            navigationItem.leftBarButtonItem = barButton
            
    


func onBackTapped(barButtonItem: UIBarButtonItem) 
    dismissViewControllerAnimated(true, completion: nil)

【讨论】:

我不想将它推送到 selectedViewController 上,因为它与那个视图控制器无关。 (它们是不同的概念)。我知道模态是正确的方法,但我需要管理堆栈并让用户来回导航。 我已经更新了我的答案,以包含您以模态方式呈现的 UINavigationController。这将为您提供所需的导航堆栈,并且当您单击后退按钮(您必须添加)时,根消息控制器可以关闭 navController。 谢谢马克。我的根 VC 如何关闭 navController 模式? 我已经更新了我的答案以包含您可以添加到 InstantMessagesViewController 以添加自定义后退按钮的代码。 非常感谢。你知道为什么当根 VC 试图解散时 deinit 没有被调用吗? (堆栈中的所有其他调用 deinit 除了堆栈中的第一个)

以上是关于如何创建以 TabBarViewController 为根的导航堆栈?的主要内容,如果未能解决你的问题,请参考以下文章