Reputation: 2025
I am displaying notifications in my application and I am having difficulties incrementing the badge number based on the number of notifications. My code is specified below:
func notifcation(model: Model) -> Void {
let calendar = Calendar.current
guard let date = model.remiderDate else {return}
let title = model.name
let body = model.desc
let comp2 = calendar.dateComponents([.year,.month,.day,.hour,.minute], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: comp2, repeats: true)
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = UNNotificationSound.default()
content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber
let identifier = "\(date)"
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if let error = error {
// Something went wrong
print(error as Any)
}
})
}
I am able to get multiple notifications but I am unable to increment the badge value to reflect the number of notifications.
The application notification also does not show up if the application is currently running but notifications work if the application is in the background.
Upvotes: 0
Views: 1288
Reputation: 1068
For anyone using firebase this should be helpful. Most the examples I looked at had deprecated payload structures. Looks like you have to keep track of the badge value in your database. In my case, the best place to increment that value was while sending a notification. Just set it back to 0 when app becomes active in your App Delegate
//Call from firestore trigger
var sendPayload = function(id, title, body){
return admin.firestore().doc('users/' + id).get().then(userDoc =>{
if (!userDoc.exists){
return null
}
var newBadge = incrementString(userDoc.get('badge'))
const token = userDoc.get('token')
if (token === null || typeof token === 'undefined'){
return null
}
admin.firestore().doc('users/' + id).set({
badge : newBadge
}, {merge: true});
console.log(token)
const payload = {
notification : {
title : title,
body : body,
sound: 'default',
badge: newBadge
},
}
return admin.messaging().sendToDevice(token,payload);
})
}
//App Delegate Client
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void){
func setBadge(){
if let newBadge = Int(info.badge){
UIApplication.shared.applicationIconBadgeNumber = newBadge
}
}
switch application.applicationState {
case .inactive:
setBadge()
case .background:
// update badge count here
setBadge()
case .active:
break
@unknown default:
fatalError("unknown state _app delegate")
}
}
func applicationDidBecomeActive(_ application: UIApplication) {
if UIApplication.shared.applicationIconBadgeNumber != 0{
UIApplication.shared.applicationIconBadgeNumber = 0
if let userID = Auth.auth().currentUser?.uid{
let dict = ["badge" : "0"]
AccountOperations.updateDocument(rootCollection: "users", doc: userID, newValueDict: dict)
}
}
}
Upvotes: 0
Reputation: 145
Actually this line content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber
is missleading. Serverside has it's own key for the app badge number. In case you want a full control on the badge coun, related to your user actions, you have to implement some logic on the UIApplicationDelegate
to reflect the desired behaviour. Something like a cache of numbers vs actions
polling and logic to work with that cache. Call it when your application will enter foreground to sanitize the badge. If your APNS server side sends you the static badge count - talk to them. As far as I know, there is no way to correct a wrong badge count from a server if your application is not running and the callbacks are not called
EDIT: probably I've confused push and local notifications in the question. Will leave the answer as a reminder for me, to read the question twice (at least) :)
Upvotes: 0
Reputation: 18591
You can increment the badge using this :
UIApplication.shared.applicationIconBadgeNumber += 1
Or :
content.badge = NSNumber(integerLiteral: UIApplication.shared.applicationIconBadgeNumber + 1)
To receive notifications whilst the app is in the foreground, your view controller should conform to the UNUserNotificationCenterDelegate
protocol and implement the userNotification:willPresent
method, and then declare your view controller as the notification delegate in viewDidLoad()
:
class ViewController: UIViewController, UNUserNotificationCenterDelegate {
override func viewDidLoad() {
super.viewDidLoad()
//...
UNUserNotificationCenter.current().delegate = self
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound])
}
}
For more on local notifations, have a look here.
Upvotes: 2