I'll start with a state chart that I created for my own use to visualize it more accurately and to consider all other states: https://docs.google.com/spreadsheets/d/e/2PACX-1vSdKOgo_F1TZwGJBAED4C_7cml0bEATqeL3P9UKpBwASlT6ZkU3iLdZnOZoevkMzOeng7gs31IFhD-L/pubhtml?gid=0&single=true
Using this chart, we can see what is actually required in order to develop a robust notification handling system that works in almost all possible use cases.
Complete solution ?
Note: A Similar answer is suggested in comments on Eric's answer, however, the state sheet helps in finding all possible scenarios as I did in my app.
Please find the complete code below and comment below if any specific case is not handled:
AppDelegate
class AppDelegate: UIResponder, UIApplicationDelegate {
private var willResignActiveCalled = false
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
NotificationUtils.shared.notification = nil
return true
}
func applicationWillResignActive(_ application: UIApplication) {
willResignActiveCalled = true
}
func applicationDidEnterBackground(_ application: UIApplication) {
willResignActiveCalled = false
}
func applicationWillEnterForeground(_ application: UIApplication) {
NotificationUtils.shared.notification = nil
}
func applicationDidBecomeActive(_ application: UIApplication) {
willResignActiveCalled = false
NotificationUtils.shared.performActionOnNotification()
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if !willResignActiveCalled { // Check if app is in inactive by app switcher, control center, or notification center
NotificationUtils.shared.handleNotification(userInfo: userInfo)
}
}
}
NotificationUtils : This is where you can write all your code to navigating to different parts of the application, handling Databases(CoreData/Realm) and do all other stuff that needs to be done when a notification is received.
class NotificationUtils {
static let shared = NotificationUtils()
private init() {}
var notification : [AnyHashable: Any]?
func handleNotification(userInfo : [AnyHashable: Any]){
if UIApplication.shared.applicationState == UIApplicationState.active {
self.notification = userInfo //Save Payload
//Show inApp Alert/Banner/Action etc
// perform immediate action on notification
}
else if UIApplication.shared.applicationState == UIApplicationState.inactive{
self.notification = userInfo
}
else if UIApplication.shared.applicationState == UIApplicationState.background{
//Process notification in background,
// Update badges, save some data received from notification payload in Databases (CoreData/Realm)
}
}
func performActionOnNotification(){
// Do all the stuffs like navigating to ViewControllers, updating Badges etc
defer {
notification = nil
}
}
}