使用 TabBarController 呈现 ViewController

Posted

技术标签:

【中文标题】使用 TabBarController 呈现 ViewController【英文标题】:Presenting ViewController with TabBarController 【发布时间】:2017-03-31 02:02:36 【问题描述】:

好的,所以每次我尝试使用以下代码呈现一个 ViewController(来自 AppDelegate 文件的“didFinishLaunchingWithOptions”函数)时,我的带有 4 个项目的 tabBar 消失了,即使显示了我想要的 ViewController:

    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)

    let tabBarController = storyBoard.instantiateViewController(withIdentifier: "theEvents") as! ThirdViewController

    self.window?.rootViewController? = tabBarController

当我尝试以下代码(也在 AppDelegate 文件的“didFinishLaunchingWithOptions”函数中)时,我什么也得不到:

    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)

    let tabBarController = storyBoard.instantiateViewController(withIdentifier: "theEvents") as! ThirdViewController

    self.window?.rootViewController?.tabBarController?.didMove(toParentViewController: tabBarController)

我已经尝试了这两者的多次迭代,但我似乎仍然无法得到我想要的......

基本上,我想要以编程方式按下其中一个按钮,以便我的第三个视图控制器成为用户在某些情况下看到的第一个视图。

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

目前还不清楚ThirdViewController 到底是什么,但我猜它是包含在标签控制器的第三个标签中的视图控制器。

标签栏控制器仍然需要是窗口的rootViewController

如果你只是想以编程方式选择标签栏控制器的某个索引,你可以这样做:

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let tabVC = storyboard.instantiateViewController(withIdentifier: "tabVC") as! UITabBarController  // however you defined your UITabBarController.
        tabVC.selectedIndex = 2   // or whatever you want
        window?.rootViewController = tabVC

如果标签栏控制器已经是根,那么您可以绕过实例化它的步骤并将其设置为根:

    if let tabVC = window?.rootViewController as? UITabBarController 
        tabVC.selectedIndex = 2
    

【讨论】:

这看起来像我想要的。我有那个,但我没有.selectedIndex,所以我想这就是我所缺少的。我会检查一下,让你知道它是怎么回事。感谢您抽出宝贵时间提供帮助。【参考方案2】:

好的,这就是我为我的应用所做的, 我所做的是,我总是导航到 MainView 并调用 performSegue 进行导航。然后我 pushViewController

class AppDelegate: UIResponder, UIApplicationDelegate 

var shortcutItem: UIApplicationShortcutItem?
var mainViewController:MainViewController?
static var  handled = false

enum ShortcutIdentifier: String 
    case AddExpense
    case AddIncome
    case AddExpenseType
    case AddIncomeType

    init?(fullIdentifier: String) 
        guard let shortIdentifier = fullIdentifier.components(separatedBy: ".").last else 
            return nil
        
        self.init(rawValue: shortIdentifier)
    


    func getUIViewController(storyboard : UIStoryboard) -> UIViewController
        return storyboard.instantiateViewController(withIdentifier:self.rawValue)
    



func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) 
    self.shortcutItem = shortcutItem
    completionHandler(handleShortcut(shortcutItem))



@discardableResult fileprivate func handleShortcut(_ shortcutItem: UIApplicationShortcutItem) -> Bool 

    let shortcutType = shortcutItem.type
    guard let shortcutIdentifier = ShortcutIdentifier(fullIdentifier: shortcutType) else 
        return false
    

    return selectTabBarItemForIdentifier(shortcutIdentifier)


fileprivate func selectTabBarItemForIdentifier(_ identifier: ShortcutIdentifier) -> Bool 
    if AppDelegate.handled  
        return false
    

    var handled = false

    guard let tabBarController = self.window?.rootViewController as? UITabBarController else 
        return false
    

    tabBarController.selectedIndex = 1

    if let contentViewController  = tabBarController.selectedViewController?.contentViewController as? MainViewController  
        mainViewController = contentViewController
    else

        guard let  navigationController = tabBarController.selectedViewController?.contentViewController.navigationController else 
            return false
        


        print(type(of:navigationController.contentViewController))
        print(navigationController.viewControllers.count)

        let _ = navigationController.popToRootViewController(animated: true)

    

    guard let rootView = mainViewController else 
        return false
    

    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    switch (identifier) 
    case .AddExpense:
        rootView.performSegue(withIdentifier: "Expences", sender: rootView)
        handled = true
    case .AddIncome:
        rootView.performSegue(withIdentifier: "Incomes", sender: rootView)
        handled = true
    case .AddExpenseType:
        rootView.performSegue(withIdentifier: "Expences Types", sender: rootView)
        handled = true
    case .AddIncomeType:
        rootView.performSegue(withIdentifier: "Incomes Types", sender: rootView)
        handled = true
    

    rootView.navigationController!.pushViewController(identifier.getUIViewController(storyboard: storyboard), animated: true)
    AppDelegate.handled = handled
    return handled


var window: UIWindow?


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 

    let theme = ThemManager.currentTheme()
    ThemManager.applyTheme(theme: theme)

    var performShortcutDelegate = true

    if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem 

        print("Application launched via shortcut")
        self.shortcutItem = shortcutItem

        performShortcutDelegate = false
    

    return performShortcutDelegate





func applicationDidEnterBackground(_ application: UIApplication) 

    AppDelegate.handled = false


func applicationDidBecomeActive(_ application: UIApplication) 

    print("Application did become active")

    guard let shortcut = shortcutItem else  return 

    print("- Shortcut property has been set")

    handleShortcut(shortcut)
    AppDelegate.handled = true
    self.shortcutItem = nil

【讨论】:

以上是关于使用 TabBarController 呈现 ViewController的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何从 TabBarController 呈现模态视图控制器

如何通过 TabBarController => NavbarController 从 Appdelegate 呈现视图控制器

presentViewController over TabBarController 导致“尝试在其视图不在窗口层次结构中的 TabBarVC 上呈现 *VC”

IBAction 使 TabBarController 应用程序崩溃

TabBarController 是不是有像 prepareForSegue 这样的拦截点?

在呈现的 ViewController/NavigationController 上获取 UITabBarController