In a SwiftUI project using SwiftData, local notifications typically use a UUID as the notification identifier. But, since I’m using SwiftData and want to avoid having multiple unique identifiers in my model, can I stringify the hashValue of the PersistentIdentifier and use that instead?
Should this be ok?
import SwiftUI
import UserNotifications
class NotificationManager {
static let shared = NotificationManager()
func scheduleNotification(for item: Item) {
let notificationId = String(item.id.hashValue)
let content = UNMutableNotificationContent()
content.title = "Items"
content.body = "Itemize the items"
content.sound = .default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: notificationId, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
print("Failed to schedule notification: (error.localizedDescription)")
}
}
}
func removeNotification(for item: Item) {
let notificationId = String(item.id.hashValue)
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [notificationId])
}
}
2
The problem is the hashValue
is unstable and will change between executions of the app.
From hashValue documentation:
Hash values are not guaranteed to be equal across different executions
of your program. Do not save hash values to use during a future
execution.
The best solution at the moment seems to be storing a notificationId in my model which imho does look a lot more cleaner than a hacky extension to extract the UUID from the id.
Updated code takes a UUID (notificationId) persisted in the Item model:
import SwiftUI
import UserNotifications
class NotificationManager {
static let shared = NotificationManager()
func scheduleNotification(for item: Item) {
let notificationId = item.notificationId.uuidString
let content = UNMutableNotificationContent()
content.title = "Items"
content.body = "Itemize the items"
content.sound = .default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: notificationId, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
print("Failed to schedule notification: (error.localizedDescription)")
}
}
}
func removeNotification(for item: Item) {
let notificationId = item.notificationId.uuidString
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [notificationId])
}
}