Значок платформы уведомлений пользователей не увеличивается - PullRequest
0 голосов
/ 14 сентября 2018

Я использую UserNotification Framework в моем приложении и отправляю локальные уведомления (не push-уведомления), и я хочу установить значок на количество полученных уведомлений, чтобы я установил количество полученных уведомлений в пользовательский по умолчанию, затем я попытался присвоить значку значок, чтобы получить номер значка, но номер значка не увеличился. Это мой код ниже

Для установки значения полученного уведомления

center.getDeliveredNotifications { notification in

    UserDefaults.standard.set(notification.count, forKey: Constants.NOTIFICATION_COUNT)
    print("notification.count \(notification.count)")
    print(".count noti \(UserDefaults.standard.integer(forKey: Constants.NOTIFICATION_COUNT))")

}

Это точно печатает номер полученного уведомления, и когда я решил установить его на свой значок, он показывает только 1

content.badge = NSNumber(value: UserDefaults.standard.integer(forKey: Constants.NOTIFICATION_COUNT))

Понятия не имею, почему значение не увеличивается каждый раз. Любая помощь будет оценена.

Или, если есть возможность всегда обновлять значок в любом месте приложения.

Ответы [ 2 ]

0 голосов
/ 16 сентября 2018

Я предполагаю, что это все локальное уведомление.

AFAIK есть решение вашего вопроса!

Когда приходит уведомление, вы находитесь либо на переднем плане, либо на заднем плане.

  • передний план: вы получаете обратный вызов userNotificationCenter(_:willPresent:withCompletionHandler:), но я не думаю, что в этом случае вы захотите увеличить значок, верно? Потому что пользователь только что видел это. Хотя я могу представить, где вам может понадобиться сделать это. Предположим, ваше приложение похоже на WhatsApp, а пользователь открыл приложение и отправляет сообщение своей матери. Затем приходит сообщение от его отца. На данный момент он не открыл сообщения между ним и его отцом, но он видит уведомление. По вашему желанию вы можете запросить getDeliveredNotifications и настроить количество значков.
  • фон: для iOS10 + версия для локальных уведомлений, вам не повезло! Потому что нет обратного звонка для вас. Уведомление доставляется в ОС и все! Используется имя application:didReceiveLocalNotification: , но это устарело . Подробнее об этом см. здесь
  • Когда пользователь нажимает (на переднем плане или на бэкэнд), вы получите userNotificationCenter(_:didReceive:withCompletionHandler:) , но это уже бесполезно, поскольку пользователь уже подтвердил получение уведомления и увеличение Значок в этом случае не имеет смысла.

Короче говоря AFAIK, вы ничего не можете сделать для локальных уведомлений.

Если это удаленное уведомление, то в application(_:didReceiveRemoteNotification:fetchCompletionHandler:) вы можете запросить доставленные уведомления и увеличить количество значков ...

EDIT:

Поскольку badgeCount прикреплен к прибывающему уведомлению, то, если вы можете обновить его badgeCount до прибытия, то все в порядке. например в 12 вечера вы всегда можете запросить список pendingNotifications. Он выдаст вам все уведомления, пришедшие после 12 часов, и при необходимости обновит их счет, например, например. уменьшить их badgeCount, если некоторые доставленные уведомления читаются. Для полного решения этого см. Ответ Carspen90 . Суть его ответа

для любого нового уведомления, которое вы хотите отправить:

  1. получите pendingNotifications
  2. фильтрует уведомления, у которых их firingDate раньше, чем новое, которое будет отправлено, и получает его count
  3. установить значок нового уведомления на badgeCount + <strong>filtered</strong>Count + 1
  4. if любое из ожидающих уведомлений имеет дату срабатывания, превышающую дату добавления нового уведомления, которое мы только что добавили, тогда мы увеличим количество badgeCount для ожидающего уведомления на 1.
  5. , очевидно, снова, когда вы взаимодействуете с доставленными уведомлениями, тогда вам нужно снова получить все pendingNotifications и уменьшить их badgeCount на 1

CAVEAT:

Вы не можете сделать это для уведомлений, для которых их триггер основан на location , потому что, очевидно, они не заботятся о времени.

0 голосов
/ 16 сентября 2018

Отправляйте локальные уведомления следующим образом:

func sendNotification(title: String, subtitle: String, body: String, timeInterval: TimeInterval) {
    let center = UNUserNotificationCenter.current()
    center.getPendingNotificationRequests(completionHandler: { pendingNotificationRequests in

        //Use the main thread since we want to access UIApplication.shared.applicationIconBadgeNumber
        DispatchQueue.main.sync {

            //Create the new content
            let content = UNMutableNotificationContent()
            content.title = title
            content.subtitle = subtitle
            content.body = body

            //Let's store the firing date of this notification in content.userInfo
            let firingDate = Date().timeIntervalSince1970 + timeInterval
            content.userInfo = ["timeInterval": firingDate]

            //get the count of pending notification that will be fired earlier than this one
            let earlierNotificationsCount: Int = pendingNotificationRequests.filter { request in

                let userInfo = request.content.userInfo
                if let time = userInfo["timeInterval"] as? Double {
                    if time < firingDate {
                        return true
                    } else {

                        //Here we update the notofication that have been created earlier, BUT have a later firing date
                        let newContent: UNMutableNotificationContent = request.content.mutableCopy() as! UNMutableNotificationContent
                        newContent.badge = (Int(truncating: request.content.badge ?? 0) + 1) as NSNumber
                        let newRequest: UNNotificationRequest =
                            UNNotificationRequest(identifier: request.identifier,
                                                  content: newContent,
                                                  trigger: request.trigger)
                        center.add(newRequest, withCompletionHandler: { (error) in
                            // Handle error
                        })
                        return false
                    }
                }
                return false
            }.count

            //Set the badge
            content.badge =  NSNumber(integerLiteral: UIApplication.shared.applicationIconBadgeNumber + earlierNotificationsCount + 1)
            let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval,
                                                            repeats: false)

            let requestIdentifier = UUID().uuidString  //You probably want to save these request identifiers if you want to remove the corresponding notifications later
            let request = UNNotificationRequest(identifier: requestIdentifier,
                                                content: content, trigger: trigger)

            center.add(request, withCompletionHandler: { (error) in
                // Handle error
            })
        }
    })
}

(Вам может потребоваться сохранить идентификаторы запросов (либо в пользовательских настройках по умолчанию, либо в основных данных, если вы хотите обновить их, либо даже отменить их).через removePendingNotificationRequests(withIdentifiers:))

Вы можете вызвать вышеуказанную функцию следующим образом:

sendNotification(title: "Meeting Reminder",
                 subtitle: "Staff Meeting in 20 minutes",
                 body: "Don't forget to bring coffee.",
                 timeInterval: 10)

Объявите свой контроллер вида как UNUserNotificationCenterDelegate:

class ViewController: UIViewController, UNUserNotificationCenterDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        UNUserNotificationCenter.current().delegate = self
    }
    //...
}

А для обработки взаимодействия с уведомлением обновите значок приложения и значок предстоящих уведомлений:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    //UI updates are done in the main thread
    DispatchQueue.main.async {
        UIApplication.shared.applicationIconBadgeNumber -= 1
    }

    let center = UNUserNotificationCenter.current()
    center.getPendingNotificationRequests(completionHandler: {requests in
        //Update only the notifications that have userInfo["timeInterval"] set
        let newRequests: [UNNotificationRequest] =
            requests
                .filter{ rq in
                    return rq.content.userInfo["timeInterval"] is Double?
                }
                .map { request in
                    let newContent: UNMutableNotificationContent = request.content.mutableCopy() as! UNMutableNotificationContent
                    newContent.badge = (Int(truncating: request.content.badge ?? 0) - 1) as NSNumber
                    let newRequest: UNNotificationRequest =
                        UNNotificationRequest(identifier: request.identifier,
                                              content: newContent,
                                              trigger: request.trigger)
                    return newRequest
        }
        newRequests.forEach { center.add($0, withCompletionHandler: { (error) in
            // Handle error
        })
        }
    })
    completionHandler()
}

Это обновит значок приложения, уменьшив его при взаимодействии уведомления ст. е. нажата. Кроме того, обновляется значок содержимого ожидающих уведомлений. Добавление запроса уведомления с тем же идентификатором просто обновляет ожидающие уведомления.

Для получения уведомлений на переднем плане и увеличения значка значка приложения, если уведомлениене взаимодействует с, реализовать это:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    DispatchQueue.main.async {
        UIApplication.shared.applicationIconBadgeNumber += 1
    }
    completionHandler([.alert, .sound])
}

Вот некоторые картинки:

  • 1-й : получение локального уведомленияications увеличивает значок приложения.Принимая во внимание, что взаимодействие с уведомлением уменьшает значок приложения.

  • 2nd : получение локальных уведомлений при закрытии приложения ( Я использовал время запускаInInval, равное 15 с, вthis ).

  • 3-е : получение уведомления в то время как на переднем плане увеличивает значок приложения, если пользователь не взаимодействует с ним.

Полный класс, используемый в моем тестовом проекте, выглядит следующим образом:

import UIKit
import UserNotifications

class ViewController: UIViewController, UNUserNotificationCenterDelegate {
    var bit = true
    @IBAction func send(_ sender: UIButton) {
        let time: TimeInterval = bit ? 8 : 4
        bit.toggle()
        sendNotification(title: "Meeting Reminder",
                         subtitle: "Staff Meeting in 20 minutes",
                         body: "Don't forget to bring coffee.",
                         timeInterval: time)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        UNUserNotificationCenter.current().delegate = self
    }

    func sendNotification(title: String, subtitle: String, body: String, timeInterval: TimeInterval) {
        let center = UNUserNotificationCenter.current()
        center.getPendingNotificationRequests(completionHandler: { pendingNotificationRequests in
            DispatchQueue.main.sync {
                let content = UNMutableNotificationContent()
                content.title = title
                content.subtitle = subtitle
                content.body = body
                let firingDate = Date().timeIntervalSince1970 + timeInterval
                content.userInfo = ["timeInterval": firingDate]
                let earlierNotificationsCount: Int = pendingNotificationRequests.filter { request in
                    let userInfo = request.content.userInfo
                    if let time = userInfo["timeInterval"] as? Double {
                        if time < firingDate {
                            return true
                        } else {
                            let newContent: UNMutableNotificationContent = request.content.mutableCopy() as! UNMutableNotificationContent
                            newContent.badge = (Int(truncating: request.content.badge ?? 0) + 1) as NSNumber
                            let newRequest: UNNotificationRequest =
                                UNNotificationRequest(identifier: request.identifier,
                                                      content: newContent,
                                                      trigger: request.trigger)
                            center.add(newRequest, withCompletionHandler: { (error) in
                                // Handle error
                            })
                            return false
                        }
                    }
                    return false
                    }.count
                content.badge =  NSNumber(integerLiteral: UIApplication.shared.applicationIconBadgeNumber + earlierNotificationsCount + 1)
                let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval,
                                                                repeats: false)

                let requestIdentifier = UUID().uuidString  //You probably want to save these request identifiers if you want to remove the corresponding notifications later
                let request = UNNotificationRequest(identifier: requestIdentifier,
                                                    content: content, trigger: trigger)

                center.add(request, withCompletionHandler: { (error) in
                    // Handle error
                })
            }
        })
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        DispatchQueue.main.async {
            UIApplication.shared.applicationIconBadgeNumber += 1
        }
        completionHandler([.alert, .sound])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        DispatchQueue.main.async {
            UIApplication.shared.applicationIconBadgeNumber -= 1
        }

        let center = UNUserNotificationCenter.current()
        center.getPendingNotificationRequests(completionHandler: {requests in
            let newRequests: [UNNotificationRequest] =
                requests
                    .filter{ rq in
                        return rq.content.userInfo["timeInterval"] is Double? 
                    }
                    .map { request in
                        let newContent: UNMutableNotificationContent = request.content.mutableCopy() as! UNMutableNotificationContent
                        newContent.badge = (Int(truncating: request.content.badge ?? 0) - 1) as NSNumber
                        let newRequest: UNNotificationRequest =
                            UNNotificationRequest(identifier: request.identifier,
                                              content: newContent,
                                              trigger: request.trigger)
                        return newRequest
            }
            newRequests.forEach { center.add($0, withCompletionHandler: { (error) in
                // Handle error
            })
            }
        })
        completionHandler()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...