13

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.

user1739040
  • 143
  • 5

3 Answers3

1

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!

Nick Toumpelis
  • 2,717
  • 22
  • 38
  • Unfortunately this doesn't work. In CloudKit the system keeps a count of the number of notifications that it has sent. If you reset it on the device then the next time CloudKit sends a notification the badge goes back to its old number plus one. Is there any work-around? – Peter B. Kramer Nov 29 '21 at 21:16
  • 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 of the need to keep supporting CKModifyBadgeOperation – Peter B. Kramer Aug 12 '22 at 03:28
0

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.

Peter B. Kramer
  • 16,385
  • 1
  • 16
  • 20
-1

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.

Clifton Labrum
  • 13,053
  • 9
  • 65
  • 128