通过NavigationController-TabBarController-NavigationController以编程方式导航

时间:2018-01-14 23:05:04

标签: ios swift uitabbarcontroller programmatically

我的基于故事板的应用程序具有以下结构:

NavigationController(NavCa) - > CollectionViewController(VCa) - >以模态呈现 - > TabBarController(TabBarC)

TabBarC有两个选项卡,每个选项卡都嵌入在自己的NavigationController中:

TabBar [0] NavigationController(NavCTab0) - > TableViewController(VC01) - > ViewController(VC02) - > ViewController(VC03)

TabBar [1] NavigationController(NavCTab1) - > ViewController(VC11) - > ViewController(VC12)

我的问题:我的一个3D QuickAction必须直接导航到VC01。

我确实检查了网站。主题Swift: Programmatically transitioning from 1 view to another via a TabBar and Navigation Controller看起来非常接近我的。我尝试了代码(AppDelegate.swift中的快速动作处理程序):

let mainSB = UIStoryboard(name: "Main", bundle: nil)
let tbc = mainSB.instantiateViewController(withIdentifier: “TabBarC”) as? TabBarController
tbc?.selectedIndex = 0
let ncTab0  = tbc?.viewControllers![0] as! UINavigationController

let vc01 = mainSB.instantiateViewController(withIdentifier: “VC01”) as! TableViewController01
let vc02 = mainSB.instantiateViewController(withIdentifier: “VC02”) as! ViewController02
let vc03 = mainSB.instantiateViewController(withIdentifier: “VC03”) as! ViewController03
let arrayOfVC = [vc01, vc02, vc03]
ncTab0.setViewControllers(arrayOfVC, animated: false)

ncTab0.popToViewController(vc01, animated: true)
self.window?.rootViewController?.present(tbc, animated: true, completion: nil)

但没有发生任何事情。输出窗口中没有任何内容。应用程序中没有任何操作(如果应用程序被终止,它将启动到VCa屏幕;如果应用程序未终止,则它会保持在快速操作之前的位置。)

非常感谢任何帮助。

P.S。我只说SWIFT。

修改

带有快速操作处理程序的我的AppDelegate.swift:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

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

        var isLaunchedFromQuickAction = false

        // Check if it's launched from Quick Action
        if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem {

            isLaunchedFromQuickAction = true
            _ = handleQuickAction(shortcutItem)
        }

        // Return false if the app was launched from a shortcut, so performAction... will not be called.
        return !isLaunchedFromQuickAction
    }

    func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        completionHandler(handleQuickAction(shortcutItem))
    }

    func handleQuickAction(_ shortcutItem: UIApplicationShortcutItem) -> Bool {

        var quickActionHandled = false
        let type = shortcutItem.type.components(separatedBy: ".").last!
        if type == "QuickAction1" {
            ... // Navigating to VC01, see piece of code above
            quickActionHandled = true
        }
    }
    return quickActionHandled
}

我在其他应用中使用的相同快速操作处理程序。该应用程序具有NavigationController结构 - > ViewController1 - > ViewController2 - > ViewController3。还有一个快速操作导航到ViewController2。它就像一个魅力。 与新应用程序的唯一区别是应用程序结构。我无法通过所有这些TabBarControllers,NavigationControllers等获得导航......

编辑2

正如所建议的那样,我尝试了Apple Sample Code(https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2)的另一种Quick Action处理方法。而且......它现在有效。部分。

如果我终止该应用程序,则3D快速操作可以完美运行。

BUT。如果我没有终止应用程序并且只在后台发送它 - 快速操作不起作用,并且在控制台中我得到相同的旧消息:'警告:尝试呈现< APP_NAME.TabBarController:0x1060b1c00> on< UINavigationController:0x106823200>其视图不在窗口层次结构中!'。

有什么想法吗?

编辑3

最终解决方案。

3D快速操作与Apple示例代码(https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2完全相同)在开关shortCutType下的AppDelegate.swift中快速操作并导航到'VC01'

case ShortcutIdentifier.first.type:
    // Handle shortcut 1 (static).
    let mainSB = UIStoryboard(name: "Main", bundle: nil)
    let tbc = mainSB.instantiateViewController(withIdentifier: "TabBarC") as? TabBarController
    self.window?.rootViewController?.dismiss(animated: true, completion: nil)
    self.window?.rootViewController?.present(tbc!, animated: true, completion: nil)
    handled = true
    break

此代码已经过测试和运作。

1 个答案:

答案 0 :(得分:0)

根据我对您的代码的理解,我认为只有三行代码就足够了

let mainSB = UIStoryboard(name: "Main", bundle: nil)
let tbc = mainSB.instantiateViewController(withIdentifier: “TabBarC”) as? TabBarController
self.window?.rootViewController.present(tbc, animated: true, completion: nil)

由于标签栏视图控制器似乎只在故事板中设置。默认情况下会选择标签控制器的第一个选项卡。

修改

针对“试图呈现......”问题的其他解决方案 您可以设置标志,并且在视图控制器viewDidLoad方法中,您可以尝试以与代码相同的方式呈现tabBarViewController。