How to do badge increment on iOS push notification

跟風遠走 提交于 2019-12-05 20:22:11

I will give my way to you :

My plan is to use KVO to listen the [UIApplication sharedApplication].applicationIconBadgeNumber

- (void)setupBadgeOperation {
    [[UIApplication sharedApplication] addObserver:self forKeyPath:@"applicationIconBadgeNumber" options:NSKeyValueObservingOptionNew context:nil];
}

And once value changed, I use [[NSNotificationCenter defaultCenter] postNotificationName:STATUS_BADGENUMBER_CHANGED object:nil] to inform the UI where needs to be modified for the change of badge.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"applicationIconBadgeNumber"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:STATUS_BADGENUMBER_CHANGED object:nil];
    }
}

There is three case of receiving a remote notification to change the [UIApplication sharedApplication].applicationIconBadgeNumber.

a. app is foreground
b. app is background
c. app is not launch

in a and b case, this method will be called:

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    void(^tapBlock)(void(^completeHandler)()) = ^(void(^completeHandler)()) { 
    // here I remove some code not related with the question
    NSNumber *badgeNumber = userInfo[@"aps"][@"badge"];
    [UIApplication sharedApplication].applicationIconBadgeNumber = badgeNumber.integerValue;
} 

in c case, there is no way to get the callback, so I will do it manually.

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[NSNotificationCenter defaultCenter] postNotificationName:STATUS_BADGENUMBER_CHANGED object:nil];
}

That's all, and works well for me.

Here my way Swift:

1) You need to set badge ( a variable you can call it whatever you want) to zero into Firebase Realtime database once you launch the app. Plus set application.applicationIconBadgeNumber = 0. Here is how I do it in AppDelegate:

func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    application.applicationIconBadgeNumber = 0

    // Reset badge number to zero
    let userID = Auth.auth().currentUser?.uid

    let dbRef = Database.database().reference()
    dbRef.child("Users Info").child(userID!).updateChildValues(["badge":"0"], withCompletionBlock: { (err, ref) in
        if err != nil {
            print(err!)
            return
        }
    })

}

2) Go to index.js where a function is triggered.

...
return admin.database().ref('/Users Info/' + owner).once('value', snapshot => {

    var ownerValue = snapshot.val();

    var badgeNumber = parseInt(ownerValue.badge) + 1;

    // Notification details.
    const payload = {
      notification: {
        title: 'You have a new request!',
        body: `A new request from ${downedBy.name}.`,
        badge:`${badgeNumber}`,
        sound: 'default',
      }
    };
    ...
    ...
    // Upload the new value of badge into Firebase to keep track of the number
    return admin.database().ref('/Users Info/' + owner).update({badge:badgeNumber});
    ...
    })

Keep your badge count in NSUserDefault for maximum availability. even if you restart your device, then also you would be able to get badge count from NSUserDefault.

When you get another payload then you could keep incrementing badge count in NSUserDefault.

Whenver we use the push notification. we have to update its badge count. Otherwise each and every time badge will be same. e.g. If you got a notification its count is 1 and you read it it will still shows badge 1. so for this you have to clear the badge. by using code like this,

  func applicationDidBecomeActive(application: UIApplication) {
        application.applicationIconBadgeNumber = 0
    }

First of all, leave it to your server guys to send you updated badge counter. Your job is only to display it, not to maintain it on your end.

You need to perform the update operations in applicationDidReceiveRemoteNotifications Delegate method like this:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]){
       let notification = userInfo["aps"] as? NSDictionary
       let badge = (notification["badge"] as String).toInt() 
       UIApplication.sharedApplication().applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + badge;

}

And in your DidBecomeActive method:

func applicationDidBecomeActive(application: UIApplication) {
       if(UIApplication.sharedApplication().applicationIconBadgeNumber!=0){
    UIApplication.sharedApplication().applicationIconBadgeNumber = 0
    }

This is with the assumption that your server sends you updated push badge counter. In , I'd do something like this to convey to the Server that push counter must be set to zero now:

var currentInstallation = PFInstallation.currentInstallation()
      if currentInstallation.badge != 0 {
        currentInstallation.badge = 0
        currentInstallation.save
       }

If I don't do this, Server will assume that Push has never been read yet and will increment the badge counter on their end on the next push and so on.

MirMiratom

Server must increment much count in @"badge" key. When you open app, you need send request to server - Reset Push Counter (badge). In applicationDidBecomeActive method.

{"aps":
    {"alert":"Notification Hub test notification2",
     "badge":20,
     "sound":"Default"}
}

You are going in a correct direction. You will have to update badge number from your payload and that's the standard way in push notifications.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!