在 SWIFT 中接收推送通知后控制加载哪个视图控制器 [英] Controlling which view controller loads after receiving a push notification in SWIFT

查看:27
本文介绍了在 SWIFT 中接收推送通知后控制加载哪个视图控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一旦我收到推送通知并滑动打开它,它只会打开我的应用程序,而不是我想要的 VC.

Once I receive a push notification and swipe to open it, it just opens my app and not the VC I want.

所以我的问题是如何加载我想要的 VC?我知道如果应用程序打开,我会将 VC 移到 didReceiveRemoteNotification 内的另一个,但如果应用程序未打开,我该怎么做?或者如果它处于后台模式?

So my question is how do I load the VC I want? I know if the app is open I would move the VC over to another inside the didReceiveRemoteNotification but how do I do it if the app isn't open? or if it is in background mode?

此外,我有两个不同的推送通知,因此我需要它来移动两个不同 VC 中的一个.如何区分不同的推送通知?

Also I have TWO different push notifications, so therefore I need it to move ONE of TWO different VCs. How can I tell the difference between different push notifactions?

谢谢.

推荐答案

已针对 Swift 4.2 更新

就像上面说的,你想在 applicationDidLaunchWithOptions 中注册远程通知:

Like it was said, you want to register to remote notifications in applicationDidLaunchWithOptions :

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
     let pushSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
    UIApplication.shared.registerUserNotificationSettings(pushSettings)
     UIApplication.shared.registerForRemoteNotifications()
}

当您从 lockScreen/Background 返回时,无法知道您将在哪个 viewController 中.我所做的是从 appDelegate 发送通知.当您收到 remoteNotification 时,会调用 appDelegate 中的 didReceiveRemoteNotification.

There is no way to know in which viewController you will be when you come back from the lockScreen/Background. What I do is I send a notification from the appDelegate. When you receive a remoteNotification, didReceiveRemoteNotification in the appDelegate is called.

 func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    let notif = JSON(userInfo) // SwiftyJSON required 

根据您的通知负载,您应该首先确保它不是 nil,然后调用一个 NSNotification,它将被应该捕获此通知的 viewControllers 捕获.这也是您可以根据收到的有效负载发布不同类型通知的地方.可能看起来像这样,以它为例:

Depending on your notification payload, you should first make sure it is not nil and then call a NSNotification that will be catched by the viewControllers that should catch this notification. This is also where you could post different kinds of notification based on payload you received. Could look like this, just take it as an example :

if notif["callback"]["type"] != nil {
  NotificationCenter.default.post(name: Notification.Name(rawValue: "myNotif"), object: nil)
  // This is where you read your JSON to know what kind of notification you received  

}

如果您收到消息通知并且由于令牌已过期而不再登录,那么视图控制器将永远不会捕获该通知,因为它永远不会被监视.

If you receive a message notification and you have not logged in anymore because the token has expired, then the notification will never be catched in the view controller because it will never be watched.

现在是在视图控制器中捕获通知的部分.在视图中:

Now for the part where you catch the notification in the view controller. In the viewWillAppear:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(self.catchIt), name: NSNotification.Name(rawValue: "myNotif"), object: nil)
}

现在你添加了这个观察者,每次在这个控制器中调用一个通知,函数 catchIt 也将被调用.您必须在要实现特定操作的每个视图控制器中实现它.

Now that you added this observer, each time a notification is called in this controller, the function catchIt will also be called. You will have to implement it in every view controller you want to implement a specific action.

func catchIt(_ userInfo: Notification){

    let prefs: UserDefaults = UserDefaults.standard
    prefs.removeObject(forKey: "startUpNotif")

    if userInfo.userInfo?["userInfo"] != nil{
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc: RedirectAppInactiveVC = storyboard.instantiateViewController(withIdentifier: "RedirectAppInactiveVC") as! RedirectAppInactiveVC
        self.navigationController?.pushViewController(vc, animated: true)
    } else {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc: RedirectAppActiveVC = storyboard.instantiateViewController(withIdentifier: "RedirectAppActiveVC") as! RedirectAppActiveVC
        self.navigationController?.pushViewController(vc, animated: true)
    }
}

不要忘记在离开视图控制器时取消订阅通知,否则视图控制器,如果仍在堆栈中,将捕获通知并执行它(你可能想要这样做,但知道你什么更安全正在进入).所以我建议在 viewWillDisappear 中取消订阅:

Don't forget to unsubscribe from the notifications when leaving the view controller, else the viewController, if still in the stack, will catch the notification and execute it (well you might want to that, but it's safer to know what you are going into). So I suggest unsubscribing in the viewWillDisappear:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.removeObserver(self)
}

这样做,您将加载您想要的viewController.现在我们还没有处理所有的病例.如果你还没有打开你的应用程序怎么办.显然,没有 UIViewController 被加载,他们都无法捕捉到通知.您想知道您是否在 appDelegate 中的 didFinishLaunchingWithOptions: 中收到了通知.我要做的是:

Doing it this way, you will load the viewController you want. Now we haven't treated all the cases yet. What if you haven't opened your application yet. Obviously, no UIViewController has been loaded, and none of them will be able to catch the notification. You want to know if you received a notification in didFinishLaunchingWithOptions: in the appDelegate. What I do is:

let prefs: UserDefaults = UserDefaults.standard
if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary {
    prefs.set(remoteNotification as! [AnyHashable: Any], forKey: "startUpNotif")
    prefs.synchronize()
}

现在,您已设置首选项,说明应用程序是使用远程通知启动的.在您的应用程序中应该首先加载的控制器中,我建议在 viewDidAppear 中执行以下操作:

Now, you have set a preference saying the application was started using a remote notification. In the controllers that should be loaded first in your application, I suggest doing the following in the viewDidAppear:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let prefs: UserDefaults = UserDefaults.standard
    if prefs.value(forKey: "startUpNotif") != nil {
        let userInfo: [AnyHashable: Any] = ["inactive": "inactive"]
        NotificationCenter.default.post(name: Notification.Name(rawValue: "myNotif"), object: nil, userInfo: userInfo as [AnyHashable: Any])
    }
}

希望有帮助.我还制作了一个 GitHub 存储库来说明本地通知:本地通知观察者模式(类似到远程通知).使用根视图控制器 Local Notifications Root Pattern 可以实现类似的逻辑,我个人认为这取决于你想要实现什么.

Hope it helps. I also made a GitHub repository to illustrate with local notifications : Local Notifications Observer Pattern (similar to Remote notifications). A similar logic can be implemented using the root view Controller Local Notifications Root Pattern, I personally think it will depend on what you want to implement.

这里的这些示例是为了说明如何简单地实现它.对于更大的项目,您最终会得到更复杂的架构,例如内部使用类似机制的协调器.

These examples are here to illustrate how it can be simply implemented. With bigger projects, you will end up with more complex architectures such as coordinators that that internally utilize similar mechanisms.

这篇关于在 SWIFT 中接收推送通知后控制加载哪个视图控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆