在保持TabBar的同时在AppDelagate中打开ViewController
在我的Xcode项目中,当用户点击通知时,我想先将它们发送到tabBar中的某个项目,然后我想实例化一个视图控制器并将对象发送到该视图控制器。 我有代码将它们发送到我想要的tabBar,但我不知道如何将它们实例化到视图控制器,同时保持TabBar和导航栏连接到视图控制器。 所有的答案都需要你改变根视图控制器,这使得当视图控制器被调用时,我失去了与我的tabBar和导航栏的连接。
一个真实生活的例子:用户收到Instagram通知说:“约翰开始关注你” – >用户点击通知 – > Instagram打开并显示通知选项卡 – >快速发送用户到“约翰”configuration文件,当用户按下后退button,它将它们发送回通知选项卡
应该知道:为什么我要去某个选项卡首先是得到该选项卡的导航控制器,因为我要去的视图控制器没有。
这里是我的工作代码发送用户到“通知”选项卡(我添加了评论像Instagram示例更好的理解):
if let tabbarController = self.window!.rootViewController as? UITabBarController { tabbarController.selectedViewController = tabbarController.viewControllers?[3] //goes to notifications tab if type == "follow" { //someone started following current user //send to user's profile and send the user's id so the app can find all the information of the user } }
首先,你将需要一个TabBarController:
let storyboard = UIStoryboard.init(name: "YourStoryboardName", bundle: nil) let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourTabBarController") as! UITabBarController
然后怀疑TabBarController的所有viewControllers
。 如果你的viewControllersembedded到UINavigationController
? 如果是这样的话,那么你可以试试一下导航控制器:
let first = storyboard.instantiateViewiController(withIdentifier: "YourFirstNavigationController") as! UINavigationController let second = storyboard.instantiateViewiController(withIdentifier: "YourSecondNavigationController") as! UINavigationController let third = storyboard.instantiateViewiController(withIdentifier: "YourThirdNavigationController") as! UINavigationController
你也应该实例化你想要的ViewController:
let desiredVC = storyboard.instantiateViewController(withIdentifier: "desiredVC") as! ExampleDesiredViewController
使所有的NavigationControllers作为TabBarController的viewControllers
:
tabBarController.viewControllers = [first, second, third]
并检查:这是关于你的select。
if tabBarController.selectedViewController == first { // Option 1: If you want to present first.present(desiredVC, animated: true, completion: nil) // Option 2: If you want to push first.pushViewController(desiredVC, animated. true) }
使rootViewController
作为rootViewController
:
self.window = UIWindow.init(frame: UIScreen.main.bounds) self.window?.rootViewController = tabBarController self.window?.makeKeyAndVisible()
最后:这是你完成的代码:
func openViewController() { let storyboard = UIStoryboard.init(name: "YourStoryboardName", bundle: nil) let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourTabBarController") as! UITabBarController let first = storyboard.instantiateViewiController(withIdentifier: "YourFirstNavigationController") as! UINavigationController let second = storyboard.instantiateViewiController(withIdentifier: "YourSecondNavigationController") as! UINavigationController let third = storyboard.instantiateViewiController(withIdentifier: "YourThirdNavigationController") as! UINavigationController let desiredVC = storyboard.instantiateViewController(withIdentifier: "desiredVC") as! ExampleDesiredViewController tabBarController.viewControllers = [first, second, third] if tabBarController.selectedViewController == first { // Option 1: If you want to present first.present(desiredVC, animated: true, completion: nil) // Option 2: If you want to push first.pushViewController(desiredVC, animated. true) } self.window = UIWindow.init(frame: UIScreen.main.bounds) self.window?.rootViewController = tabBarController self.window?.makeKeyAndVisible() }
如果您想在点击通知时显示或推送ViewController? 尝试类似的东西:
extension AppDelegate: UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { switch response.actionIdentifier { case UNNotificationDefaultActionIdentifier: openViewController() completionHandler() default: break; } } }
在我上一个实时项目中,我使用了和你一样的方法。 所以即使我怀疑这个方法是处理AppDelegate推送通知的正确还是理想的(我还有很多东西需要在iOS中学习),我还是分享它,因为它对我很有用,我相信代码仍然可读,相当干净。
关键是要知道你的屏幕的水平或堆栈。 什么是childViewControllers,topMost屏幕,在底部的一个,等等…
然后,如果您现在准备推送到某个屏幕,则当然需要当前屏幕的导航控制器。
例如,这个代码块来自我的项目的AppDelegate:
func handleDeeplinkedJobId(_ jobIdInt: Int) { // Check if user is in Auth or in Jobs if let currentRootViewController = UIApplication.shared.keyWindow!.rootViewController, let presentedViewController = currentRootViewController.presentedViewController { if presentedViewController is BaseTabBarController { if let baseTabBarController = presentedViewController as? BaseTabBarController, let tabIndex = TabIndex(rawValue: baseTabBarController.selectedIndex) { switch tabIndex { case .jobsTab: .... .... if let jobsTabNavCon = baseTabBarController.viewControllers?.first, let firstScreen = jobsTabNavCon.childViewControllers.first, let topMostScreen = jobsTabNavCon.childViewControllers.last { ... ...
所以,正如你所看到的,我知道屏幕的层次结构,通过使用这些知识以及通过使用断点和printobject (po)
来检查我是否在正确的屏幕上的耐心,我得到了正确的参考。 最后,在上面的代码中,我有topMostScreen
引用,如果需要,我可以使用该屏幕的navigationController推到新的屏幕。
希望这可以帮助!
我可以想到两种方法来做到这一点:
1)如果该视图控制器是一个UINavigationController,你可以简单地从任何地方推送configuration文件:
if let tabNavigationController = tabbarController.viewControllers?[3] as? UINavigationController { tabbarController.selectedViewController = tabNavigationController let profileViewController = ProfileViewController(...) // ... set up the profile by setting the user id or whatever you need to do ... tabNavigationController.push(profileViewController, animated: true) // animated or not, your choice ;) }
2)另外,我喜欢做的是直接从我的视图控制器子类(在这种情况下,PostListViewController)控制这样的事情。 我在我所有的项目中都包含了一个swift文件中的帮助器方法:
extension UIViewController { var containedViewController: UIViewController { if let navController = self as? UINavigationController, let first = navController.viewControllers.first { return first } return self } }
然后我会这样做推新视图控制器:
if let tabViewController = tabbarController.selectedViewController { tabbarController.selectedViewController = tabViewController if let postListViewController = tabViewController.containedViewController as? PostListViewController { postListViewController.goToProfile(for: user) // you need to get the user reference from somewhere first } }
- 为什么AppDelegate.swift窗口是可选的?
- 我如何连接UITableView到我的Appdelegate.m?
- 如何从其他ViewController中更改AppDelegate中的RootViewController?
- iOS:如何在X小时内每隔一小时在睡眠模式下自动发送电子邮件与iPad?
- 用接口控制器重复架构x86_64的符号
- 从UIViewController更改AppDelegate的属性不起作用
- 从应用程序委托获取当前的视图控制器(模态是可能的)
- APPDelegate中的openURL转换错误NSString – > String(Swift和iOS8)
- 如何从AppDelegate中移动这些stream程,并从每个Call中设置个别代理?