CKModifyBadgeOperation is deprecated in iOS 11. Anyone know an alternative approach?

630 views Asked by At

I have searched, and I cannot find an example. I have also tried adapting this code (recommended elsewhere (CloudKit won't reset my badge count to 0):

func resetBadgeCounter() {
    let badgeResetOperation = CKModifyBadgeOperation(badgeValue: 0)
    badgeResetOperation.modifyBadgeCompletionBlock = { (error) -> Void in
        if error != nil {
            print("Error resetting badge: \(String(describing: error))")
        }
        else {
            UIApplication.shared.applicationIconBadgeNumber = 0
        }
    }
    CKContainer.default().add(badgeResetOperation)
}

This works for now, but is no longer supported, and may go away soon.

I thought perhaps I should use a CKModfyRecordsOperation or some other CKDatabaseOperation, but I can't even guess how.

3

There are 3 answers

2
Clifton Labrum On BEST ANSWER

It's probably best to just track the items you are counting and set the app badge count yourself. I reference a local database that has my items in it, and I return the total and set my app badge accordingly.

2
Nick Toumpelis On

I hope this helps someone as there doesn't seem to be another solution/workaround to this.

  1. Create a Notification Service Extension (UNNotificationServiceExtension) for your app. It is fairly straightforward and is described in detail in Modifying Content in Newly Delivered Notifications. You might already have one, if you do any kind of processing on incoming notifications.

  2. Within the extension, you typically do all the processing of the notification in override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void). The request comes with the content of the notification, which includes the badge number. You can then modify that and pass on to the contentHandler to be displayed. (If you are unsure how to do this, check the link above; it has detailed instructions and code.)

  3. To keep track and reset the badge number when needed, you need to take advantage of an app group (e.g. group.com.tzatziki). This way you can share data between the app and the extension. Creating an app group in Xcode can be done by adding the relevant capability and is explained in App Extension Programming Guide: Handling Common Scenarios.

  4. Use a storage mechanism (within the app group) to keep track of the badge count, e.g. UserDefaults, and use it in the extension to update the badge count. In the aforementioned override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void), you could write something like this:

    let badgeNumber = UserDefaults(suiteName: "group.com.tzatziki")?.value(forKey: "badgeNumber") as? NSNumber ?? NSNumber(integerLiteral: 0)
    let badgeNumberInt = badgeNumber.intValue + 1
    notificationContent.badge = NSNumber(value: badgeNumberInt)
    UserDefaults(suiteName: "group.io.prata")?.setValue(notificationContent.badge, forKey: "badgeNumber")
    

where notificationContent is an instance of UNMutableNotificationContent, originating from request.content.mutableCopy() as? UNMutableNotificationContent

  1. Now, the only thing left to do is to reset the badge count in your app, in the shared UserDefaults and in UIApplication.shared.applicationIconBadgeNumber.

Cheers!

0
Peter B. Kramer On

It was reported here: https://levelup.gitconnected.com/how-to-reset-badge-value-of-cloudkit-remote-notification-on-ios-ipados-15-46726a435599 that Apple is aware that they need to maintain CKModifyBadgeOperation until they come up with a replacement API. There is no other solution to this problem because CloudKit resets the badge number whenever it pushes a new notification.