Значок push-уведомления в приложении не обновляется при нажатии на значок приложения

У меня возникли некоторые проблемы с корректным обновлением ярлыка значка в приложении. Я хочу что-то, что делает это:

Этот красный значок появляется каждый раз, когда получено push-уведомление. Я правильно получаю значок push-уведомления на значке приложения на iPhone; однако этот красный значок внутри приложения появляется только в том случае, если я нажимаю на баннер для push-уведомления, ИЛИ, если я уже внутри приложения.

Моя проблема в том, что он не появляется, если я нажимаю на иконку самого приложения. Мне бы хотелось, чтобы ярлык в приложении обновлялся, даже когда приложение находится в фоновом режиме, вроде того, как приложение 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 при каждом получении push-уведомления:

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

Я был бы очень признателен за любую помощь, так как я застрял на этом в течение нескольких дней.

РЕДАКТИРОВАТЬ: изменил название

1 ответ

Решение

Во-первых, вам не нужно обращаться с 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
}

Кроме того, проблема заключается в том, что вы не обновляете значок кнопки при загрузке View Controller. Вы обновляете их только тогда, когда вы получаете новое уведомление И Контроллер Представления виден. Короче, попробуйте это на вашем View Controller:

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
}

И последнее, но не менее важное: когда вы получаете удаленное уведомление, вы передаете его func handleRemoteNotifications(application: UIApplication, userInfo: NSDictionary) внутри вашего AppDelegate. Это в свою очередь посты NSNotification к объектам, которые его слушают. Однако может быть или не быть ViewController, потому что он мог быть освобожден, когда приложение находилось в фоновом режиме. Таким образом, эти строки кода никогда не вызываются при получении удаленного уведомления:

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

Попробуйте переместить строки выше на ваш AppDelegatefunc handleRemoteNotifications(application: UIApplication, userInfo: NSDictionary) метод.

Другие вопросы по тегам