My Storyboard based app has following structure:
NavigationController (NavCa) —> CollectionViewController (VCa) —> present modally —> TabBarController (TabBarC)
TabBarC has two tabs, each embedded in own NavigationController:
TabBar[0] NavigationController (NavCTab0) —> TableViewController (VC01) —> ViewController (VC02) —> ViewController (VC03)
TabBar[1] NavigationController (NavCTab1) —> ViewController (VC11) —> ViewController (VC12)
MY PROBLEM: One of my 3D QuickAction must navigate directly to VC01.
I did check through the site. The topic Swift: Programmatically transitioning from 1 view to another via a TabBar and Navigation Controller looks very close to mine. I tried the code (quick action handler in 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)
but nothing happening. Nothing comes out in output window. Nothing happens in the app (if the app was terminated, it starts to VCa screen; if the app was not terminated, it stays where it was before quick action).
Any help is highly appreciated.
P.S. I speak only SWIFT.
EDIT
My AppDelegate.swift with Quick Action Handler:
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
}
The same quick action handler I use in my other app. That app has the structure NavigationController --> ViewController1 --> ViewController2 --> ViewController3. And there also one of the quick action navigates to the ViewController2. It works like a charm. The only difference with the new app is the app structure. I cannot win the navigation through all these TabBarControllers, NavigationControllers etc...
EDIT 2
As suggested I tried another Quick Action handling approach from Apple Sample Code (https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2). And... It works now. Partly.
If I terminate the app the 3D Quick Actions work perfectly.
BUT. If I do not terminate app and only send it in background - the Quick Actions do not work and in Console I get the same old message: 'Warning: Attempt to present <APP_NAME.TabBarController: 0x1060b1c00> on <UINavigationController: 0x106823200> whose view is not in the window hierarchy!'.
Any ideas?
EDIT 3
THE FINAL SOLUTION.
3D Quick Action made exactly as in Apple Sample Code (https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2) In AppDelegate.swift under the switch shortCutType
for quick action with navigation to '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
This code tested and works.