iosswiftunnotificationserviceextension

Detect main app state in its extension (NotificationService)


Context

I'm developing an iOS messaging app with a need to accurately manage badge counts for unread messages. When the app is running (either in foreground or background), I can query the server for the exact unread count within didReceiveRemoteNotification or userNotificationCenter(_:willPresent:) handlers.

Problem

However, I'm struggling with badge count management when the app is completely terminated. In this case, I need to rely on a NotificationService extension to increment the badge count. My concern is: how can my NotificationService extension detect whether the main app is running? I want to avoid badge count inconsistencies where:

Question

What's the most reliable way for the NotificationService extension to detect the main app's running state, and what synchronization mechanisms should I implement to prevent data races when updating badge counts across these two contexts?


Solution

  • There are few ways you can achieve synchronization of your app and its extension but I think using UserDefaults via app group is the easiest:

    In applicationDidBecomeActive:

    let userDefaults = UserDefaults(suiteName: "com.yourapp.shared")
    userDefaults?.set(true, forKey: "isAppActive")
    

    In the NotificationService extension:

    let userDefaults = UserDefaults(suiteName: "com.yourapp.shared")
    if let isAppActive = userDefaults?.bool(forKey: "isAppActive"), !isAppActive {
        // increment badge count
    }
    

    In applicationWillTerminate:

    let userDefaults = UserDefaults(suiteName: "com.yourapp.shared")
    userDefaults?.set(false, forKey: "isAppActive")
    

    However, note that this solution won't work as expected if your app is crashing as applicationWillTerminate won't be called in this case. So don't let it crash :)