通过 NavigationController-TabBarController-NavigationController 以编程方式导航
Navigate programmatically through NavigationController-TabBarController-NavigationController
我的基于 Storyboard 的应用程序具有以下结构:
NavigationController (NavCa) —> 集合ViewController (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。
我确实浏览了网站。 这个话题看起来很接近我的。我尝试了代码(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)
但什么也没发生。输出 window 没有任何结果。应用程序没有任何反应(如果应用程序被终止,它会开始到 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 示例代码 (https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2) 中的另一种快速操作处理方法。而且...现在可以使用了。部分.
如果我终止应用程序,3D 快速操作将完美运行。
但是。如果我不终止应用程序并且只在后台发送它 - 快速操作不起作用并且在控制台中我收到相同的旧消息:'Warning: Attempt to present <APP_NAME.TabBarController: 0x1060b1c00> on <UINavigationController: 0x106823200> whose view is not in the window hierarchy!'.
有什么想法吗?
编辑 3
最终解决方案。
3D Quick Action 完全按照 Apple 示例代码 (https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2) 在 AppDelegate.swift 中切换 shortCutType
以快速操作导航至 '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
此代码经过测试并有效。
根据我对你的代码的理解,我觉得三行代码就足够了
let mainSB = UIStoryboard(name: "Main", bundle: nil)
let tbc = mainSB.instantiateViewController(withIdentifier: “TabBarC”) as? TabBarController
self.window?.rootViewController.present(tbc, animated: true, completion: nil)
因为标签栏视图控制器似乎只在情节提要中设置。默认选中tabbar Controller的第一个tab
编辑
"attempt to present ...."问题的其他解决方案
您可以设置标志,并在视图控制器 viewDidLoad 方法中尝试以与代码相同的方式呈现 tabBarViewController。
我的基于 Storyboard 的应用程序具有以下结构:
NavigationController (NavCa) —> 集合ViewController (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。
我确实浏览了网站。
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)
但什么也没发生。输出 window 没有任何结果。应用程序没有任何反应(如果应用程序被终止,它会开始到 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 示例代码 (https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2) 中的另一种快速操作处理方法。而且...现在可以使用了。部分.
如果我终止应用程序,3D 快速操作将完美运行。
但是。如果我不终止应用程序并且只在后台发送它 - 快速操作不起作用并且在控制台中我收到相同的旧消息:'Warning: Attempt to present <APP_NAME.TabBarController: 0x1060b1c00> on <UINavigationController: 0x106823200> whose view is not in the window hierarchy!'.
有什么想法吗?
编辑 3
最终解决方案。
3D Quick Action 完全按照 Apple 示例代码 (https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545-Intro-DontLinkElementID_2) 在 AppDelegate.swift 中切换 shortCutType
以快速操作导航至 '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
此代码经过测试并有效。
根据我对你的代码的理解,我觉得三行代码就足够了
let mainSB = UIStoryboard(name: "Main", bundle: nil)
let tbc = mainSB.instantiateViewController(withIdentifier: “TabBarC”) as? TabBarController
self.window?.rootViewController.present(tbc, animated: true, completion: nil)
因为标签栏视图控制器似乎只在情节提要中设置。默认选中tabbar Controller的第一个tab
编辑
"attempt to present ...."问题的其他解决方案 您可以设置标志,并在视图控制器 viewDidLoad 方法中尝试以与代码相同的方式呈现 tabBarViewController。