【问题标题】:How to do badge increment on iOS push notification如何在 iOS 推送通知上增加徽章
【发布时间】:2016-11-23 11:57:54
【问题描述】:

我目前正在从有效负载中获取徽章。但是我如何更新该值。

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

当我发送它时,它总是在徽章编号中显示 1,但是当我进入应用程序并退出时,它会得到更新。正是因为这个,

func applicationDidBecomeActive(application: UIApplication) {
        UIApplication.sharedApplication().applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + 1
    }

但是当我发送新的推送通知时,它再次在图标中显示 1 作为徽章编号。 我应该怎么做,据我了解,我应该在发送有效负载时发送更新的徽章。为此,我必须处理后端。

除此之外还有什么建议可以在应用程序内部处理吗?

【问题讨论】:

    标签: ios push-notification swift2 badge


    【解决方案1】:

    如果你的项目有通知扩展,你可以在里面设置徽章。

    首先启用应用组并将您的徽章计数从应用通知服务扩展保存到UserDefaults。我们正在使用应用程序组,因为我们需要在打开应用程序时从AppDelegate 清除徽章计数。 您也可以通过通知服务扩展将徽章的值设置为bestAttemptContent.badge

    在通知服务扩展中:

    if let userDefaults = UserDefaults(suiteName: "group.com.bundle.appname") {
    
        let badgeCount = userDefaults.integer(forKey: "badgeCount")
        if badgeCount > 0 {
            userDefaults.set(badgeCount + 1, forKey: "badgeCount")
            bestAttemptContent.badge = badgeCount + 1 as NSNumber
        } else {
    
            userDefaults.set(1, forKey: "badgeCount")
            bestAttemptContent.badge = 1
        }
    }
    

    在 AppDelegate 中,您可以清除徽章...并在 userdefaults 上将徽章的值设置为零

    if let userDefaults = UserDefaults(suiteName: "group.com.bundle.appname") {
        userDefaults.set(0, forKey:"badgecount")
    }
    UIApplication.shared.applicationIconBadgeNumber = 0
    

    【讨论】:

      【解决方案2】:

      我会给你我的路:

      我的计划是使用KVO来收听[UIApplication sharedApplication].applicationIconBadgeNumber

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

      一旦值发生变化,我会使用[[NSNotificationCenter defaultCenter] postNotificationName:STATUS_BADGENUMBER_CHANGED object:nil] 通知 UI 需要在哪里修改以更改徽章。

      - (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];
          }
      }
      

      收到远程通知更改[UIApplication sharedApplication].applicationIconBadgeNumber的三种情况。

      一个。应用程序是前台
      湾。应用程序是背景
      C。应用未启动

      在a和b的情况下,会调用这个方法:

      - (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;
      } 
      

      在c的情况下,没有办法获取回调,所以我将手动进行。

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

      就是这样,对我来说效果很好。

      【讨论】:

      • 再次,目标 C!问题是关于 Swift 的。
      • 它在 Swift 中不起作用,因为 KVO 属性必须标记为“动态”。 applicationIconBadgeNumber 不是
      • 解决方案可能是将 objc 添加到您的 swift 项目中
      【解决方案3】:

      这是斯威夫特的方式:

      1) 启动应用程序后,您需要在 Firebase 实时数据库中设置徽章(您可以随意调用它的变量)为零。加上设置 application.applicationIconBadgeNumber = 0。这是我在 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) 转到触发函数的 index.js。

      ...
      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});
          ...
          })
      

      【讨论】:

      • 应该被投赞成票,它是完美的答案,我以这种方式实现了它并且效果很好!
      【解决方案4】:

      首先,让您的服务器人员向您发送更新的徽章计数器。你的工作只是展示它,而不是最终维护它。

      你需要像这样在applicationDidReceiveRemoteNotificationsDelegate 方法中执行更新操作:

      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;
      
      }
      

      在你的DidBecomeActive 方法中:

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

      这是假设您的服务器向您发送更新的推送徽章计数器。在,我会做这样的事情来传达给服务器推送计数器现在必须设置为零:

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

      如果我不这样做,服务器将假定推送尚未被读取,并会在下一次推送时增加其末端的标记计数器,依此类推。

      【讨论】:

        【解决方案5】:

        将您的徽章计数保留在 NSUserDefault 中以获得最大可用性。即使您重新启动设备,您也可以从 NSUserDefault 获取徽章计数。

        当您获得另一个有效负载时,您可以在 NSUserDefault 中继续增加徽章计数。

        【讨论】:

          【解决方案6】:

          每当我们使用推送通知时。 我们必须更新它的徽章数量。否则每次徽章都是一样的。 例如如果您收到通知,其计数为 1,并且您阅读了它,它仍会显示徽章 1。因此,您必须清除徽章。 通过使用这样的代码,

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

          【讨论】:

          • 这是客观的C。问题是关于swift的
          • 尽管如此,任何懂这两种语言的人都应该很容易翻译它。但是你仍然应该添加这个的 swift 版本
          【解决方案7】:

          服务器必须在@"badge" 键中增加很多计数。当您打开应用程序时,您需要向服务器发送请求 - 重置推送计数器(徽章)。在applicationDidBecomeActive 方法中。

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

          【讨论】:

            【解决方案8】:

            处理徽章的最佳解决方案是使用您可以创建的通知扩展。通知扩展,还使用 ​​KVO 更新应用程序中的徽章。 和应用程序组,用于保存徽章数量并在应用程序中管理。 当您收到通知时,您可以阅读您有多少通知,并将通知徽章添加到该通知并更新您的通知

            guard let content = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
                    contentHandler(request.content)
                    return
                }
            
                if let badge = bestAttemptContent?.badge as? Int {
                    let newBadge = badge + NotificationManangerBridge.shared.getTotalBadge()
                    content.badge = NSNumber(value: newBadge)
                    NotificationManangerBridge.shared.updateTotalBadge(badgeCount: newBadge)
            
                } else {
                    content.badge = 0
                }
                guard let notification = bestAttemptContent?.copy() as? UNNotificationContent else { return }
                contentHandler(notification)
            

            【讨论】:

              【解决方案9】:

              你正朝着正确的方向前进。您必须从有效负载中更新徽章编号,这是推送通知的标准方式。

              【讨论】:

              • 这是评论,不是答案。
              • @Droppy 请检查她提到的问题我应该怎么做并征求建议。
              • @JRafaelM 没关系。我会在回答时牢记这一点。
              猜你喜欢
              • 1970-01-01
              • 2012-06-24
              • 1970-01-01
              • 2010-12-28
              • 2016-06-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多