如何创建以 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 为根的导航堆栈?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式创建 UICollectionViewCell

如何以编程方式创建 DragEvent?

如何以编程方式创建按钮?

如何以编程方式创建位图?

如何以编程方式创建重叠栏按钮项

如何以编程方式向以编程方式创建的 UIView 添加约束?