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.
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:
NotificationService
should increment badgesWhat'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?
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 :)