单击应用程序图标时推送通知 in-app 徽章图标未更新

Push notification in-app badge icon not updating when clicking on app icon

我在正确更新 in-app 徽章图标标签时遇到了一些麻烦。我想要这样的东西:

只要收到推送通知,就会出现这个红色图标。我在 iPhone 上的应用程序图标上正确获得了推送通知标志;但是,只有当我按下推送通知的横幅或者我已经在应用程序中时,应用程序内的这个红色图标才会出现。

我的问题是,如果我按下实际的应用程序图标,它不会出现。我希望应用程序内的标签即使在应用程序处于后台时也能更新,就像 facebook 应用程序在通知地球图标顶部有图标一样。

我将在 AppDelegate 中展示相关方法(省略标记等):

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let userInfo: AnyObject? = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey]
    if userInfo != nil {
        handleRemoteNotifications(application, userInfo: userInfo! as! NSDictionary)
        return true
    }

    if application.applicationState != UIApplicationState.Background {
        let oldPushHandlerOnly = !self.respondsToSelector(Selector("application:didReceiveRemoteNotification:fetchCompletionHandler:"))
        let noPushPayload: AnyObject? = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey]
        if oldPushHandlerOnly || noPushPayload != nil {
            PFAnalytics.trackAppOpenedWithLaunchOptionsInBackground(launchOptions, block: nil)             
        }
    }

    return true
}

func handleRemoteNotifications(application: UIApplication, userInfo: NSDictionary) {
    if let type: String = userInfo["type"] as? String {
        switch (type) {
        case "follow":
            NSNotificationCenter.defaultCenter().postNotificationName("commentNotification", object: self)
        case "comment":
            NSNotificationCenter.defaultCenter().postNotificationName("commentNotification", object: self)
        default:
            return
        }
    }
}

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

    let installation = PFInstallation.currentInstallation()
    if installation.badge != 0 {
        installation.badge = 0
        installation.saveEventually()
    }
}

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
    if let badgeNumber: Int = userInfo["badge"] as? Int {
        application.applicationIconBadgeNumber = badgeNumber
    }

    handleRemoteNotifications(application, userInfo: userInfo)

    if application.applicationState == .Inactive {
        PFAnalytics.trackAppOpenedWithRemoteNotificationPayloadInBackground(userInfo, block: nil)
    }

    handler(.NewData)
}

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    if application.applicationState == .Inactive  {
        // The application was just brought from the background to the foreground,
        // so we consider the app as having been "opened by a push notification."
        PFAnalytics.trackAppOpenedWithRemoteNotificationPayloadInBackground(userInfo, block: nil)
        handleRemoteNotifications(application, userInfo: userInfo)
    }
}

ViewController 中,我正在调用 viewDidAppear 中的方法并使其在每次收到推送通知时更新标签并将数字增加 1:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    followLabelNumber = NSUserDefaults.standardUserDefaults().integerForKey("followNumberKey")
    commentLabelNumber = NSUserDefaults.standardUserDefaults().integerForKey("commentNumberKey")

    NSNotificationCenter.defaultCenter().removeObserver(self, name: "followNotification", object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector:"followNotificationReceived:", name:"followNotification", object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: "commentNotification", object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector:"commentNotificationReceived:", name:"commentNotification", object: nil)


    self.navigationController?.navigationBarHidden = true
}

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

func followNotificationReceived(notification: NSNotification) {
    if let number = followLabelNumber {
        let aNumber = makeIncrementer(forIncrement: 1)
        followLabelNumber = number + aNumber()
        NSUserDefaults.standardUserDefaults().setInteger(followLabelNumber!, forKey: "followNumberKey")
        NSUserDefaults.standardUserDefaults().synchronize()
        profileNotificationLabel.hidden = false
        profileNotificationLabel.text = String(followLabelNumber!)
        hasReceivedFollowNotification = true
    }
}

func commentNotificationReceived(notification: NSNotification) {
    if let number = commentLabelNumber {
        let aNumber = makeIncrementer(forIncrement: 1)
        commentLabelNumber = number + aNumber()
        NSUserDefaults.standardUserDefaults().setInteger(commentLabelNumber!, forKey: "commentNumberKey")
        NSUserDefaults.standardUserDefaults().synchronize()
        commentsNotificationLabel.hidden = false
        commentsNotificationLabel.text = String(commentLabelNumber!)
        hasReceivedCommentNotification = true
    }
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

非常感谢任何人的帮助,因为我已经坚持了几天了。

编辑:更改标题

首先,您不需要自己处理 application.applicationIconBadgeNumber,因为您使用的是 Parse:

//You don't need these...
if (application.applicationIconBadgeNumber != 0) {
    application.applicationIconBadgeNumber = 0
}

//Because these lines will set the application's icon badge to zero
let installation = PFInstallation.currentInstallation()
if installation.badge != 0 {
    installation.badge = 0
    installation.saveEventually()
}

你也不需要这个:

//Because Parse handles that for you
if let badgeNumber: Int = userInfo["badge"] as? Int {
    application.applicationIconBadgeNumber = badgeNumber
}

此外,问题似乎是您在加载视图控制器时没有更新按钮的徽章。您仅在收到新通知并且视图控制器可见时才更新它们。简而言之,在你的视图控制器上试试这个:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    followLabelNumber = NSUserDefaults.standardUserDefaults().integerForKey("followNumberKey")
    commentLabelNumber = NSUserDefaults.standardUserDefaults().integerForKey("commentNumberKey")

    //BEGIN SUGGESTED CODE
    profileNotificationLabel.hidden = followLabelNumber > 0
    profileNotificationLabel.text = String(followLabelNumber!)

    commentsNotificationLabel.hidden = commentLabelNumber > 0
    commentsNotificationLabel.text = String(commentLabelNumber!)
    //END SUGGESTED CODE

    NSNotificationCenter.defaultCenter().removeObserver(self, name: "followNotification", object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector:"followNotificationReceived:", name:"followNotification", object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: "commentNotification", object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector:"commentNotificationReceived:", name:"commentNotification", object: nil)


    self.navigationController?.navigationBarHidden = true
}

最后但并非最不重要的一点是,每当您收到远程通知时,您都会将其传递给 AppDelegate 中的 func handleRemoteNotifications(application: UIApplication, userInfo: NSDictionary)。这反过来将 NSNotification 发送到正在收听它的对象。但是,可能有也可能没有 ViewController,因为它可能在应用程序处于后台时已被释放。因此,当您收到远程通知时,这些代码行永远不会被调用:

NSUserDefaults.standardUserDefaults().setInteger(followLabelNumber!, forKey: "followNumberKey")
NSUserDefaults.standardUserDefaults().synchronize()

尝试将上面的行移动到您的 AppDelegatefunc handleRemoteNotifications(application: UIApplication, userInfo: NSDictionary) 方法。