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

4

14

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.

Newsboy answered 28/11, 2017 at 22:28 Comment(2)
Any news on this?Gastrostomy
As of Aug 2024 CKModifyBadgeOperation does not work at all & returns an error when run. There is currently no way to clear the incrementing of badging without adding an extension and manually setting the badge number.Signalman
C
-2

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.

Connubial answered 31/8, 2018 at 4:40 Comment(2)
This doesn't work for remote notifications. It works locally but the next time a remote notification comes in the badge number becomes 2 not 1.Officious
This remains a real problem. Is there any work-around?Officious
M
0

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!

Macrophysics answered 21/9, 2020 at 20:4 Comment(2)
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?Officious
It was reported here: levelup.gitconnected.com/… that Apple is aware of the need to keep supporting CKModifyBadgeOperationOfficious
O
0

This remains an issue!!!! The new method (setBadgeCount) does not reset the badge count to 0 in CloudKit. When CloudKit sends its next alert the count is incremented from its former, non 0, value. And now CKModifyBadgeOperation is no longer working.

Previous Post:

New method in iOS 16:

            [[UNUserNotificationCenter currentNotificationCenter] setBadgeCount:0 withCompletionHandler:nil];

Previous post:

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.

Officious answered 12/8, 2022 at 3:30 Comment(2)
In the current Xcode Version 16.0 beta 3, CKModifyBadgeOperation is no longer supported, apparently without any replacement. Too bad!Polarity
See the post above. Use: [[UNUserNotificationCenter currentNotificationCenter] setBadgeCount:0 withCompletionHandler:nil];Officious
O
0

This problem remains but I have now found an acceptable work-around!!! The 'new':

[[UNUserNotificationCenter currentNotificationCenter] setBadgeCount:0 withCompletionHandler:^(NSError *error){}];

does NOT reset the badge count in CloudKit. So if you are using

notification.shouldBadge=YES;

then each time a new CKQuerySubscription hits, the incremented badge count is displayed. And there is no way to set it to zero anymore (thanks Apple!). My work-around is to use

notification.shouldBadge=NO;

and pair each CKQuerySubscription with another CKQuerySubscription using the same predicate but making it a silent notification using

notification.shouldSendContentAvailable = YES;

This works while the app is in background. I receive the silent notification in

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler  {

and increment a local badge count and use the 'new' method above to display it. I set a zero value to the variable when the app enters foreground and I use

    [[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];  

to clean up the Notification Center.

I look forward to Apple restoring some way of setting the badge count to zero in CloudKit so we can go back to simply using

notification.shouldBadge=YES;
Officious answered 1/8 at 4:25 Comment(2)
Don't forget to set "Remote notifications" under "Background Modes" under the Target "Signing & Capabilities"Officious
- and you have to add the new subscriptions in the Development (capital "D" - in Entitlements File under com.apple.developer.icloud..) before switching back to Production.Officious
C
-2

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.

Connubial answered 31/8, 2018 at 4:40 Comment(2)
This doesn't work for remote notifications. It works locally but the next time a remote notification comes in the badge number becomes 2 not 1.Officious
This remains a real problem. Is there any work-around?Officious

© 2022 - 2024 — McMap. All rights reserved.