Hi Apple Engineer - I hate to post this message because I really wanted to be mistaken in my original post, but I just deployed an updated version of my app and previously scheduled local notifications were NOT delivered after the update. I carefully tested this with the user who originally brought this issue to my attention, by asking him to: 1) schedule a notification right before the version update and then 2) allow the app to update silently in the background. After the update, the local notification was NOT delivered. I did NOT change the app's bundle ID, nor am I using any sort of third party tool. The user who reported this issue has an iPhone 14 Pro Max, iOS 18.2.1, and allowed the app to update silently in the background. After re-launching the app, local notifications continued as before. So, it does appear to be the case that the update breaks previously scheduled local notifications until the app is relaunched.
I've included my code to schedule local notifications below. I'm running this code when my app changes phase and moves to the .background. If the issue I'm describing with scheduled local notifications is NOT the expected behavior, do you see anything in my code that would cause this?
func createLocalNotifications() {
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
// Clear all the old notifications to replace them with newly scheduled notifications in this function
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
let context = sharedModelContainer.mainContext
var query = FetchDescriptor<Item>(predicate: #Predicate { item in item.reminder == true},
sortBy: [SortDescriptor(\Item.reminderDate,
order: .forward)])
query.fetchLimit = 60
do {
let items = try context.fetch(query)
for notificationItem in items {
if notificationItem.reminder == true {
let content = UNMutableNotificationContent()
content.title = "Reminder"
content.body = notificationItem.name
content.sound = .default
// Local notification trigger
let calendar = Calendar.current
var triggerDate = calendar.dateComponents([Calendar.Component.day, Calendar.Component.month, Calendar.Component.year], from: notificationItem.reminderDate!)
triggerDate.hour = Calendar.current.component(.hour, from: userSettings.reminderTimeOfDay)
triggerDate.minute = Calendar.current.component(.minute, from: userSettings.reminderTimeOfDay)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
// Local notification request with content and trigger
let notificationUUID = "\(notificationItem.id)" + "-localNotificationID"
let request = UNNotificationRequest(identifier: notificationUUID, content: content, trigger: trigger)
// Schedule the request
UNUserNotificationCenter.current().add(request) { error in
guard error == nil else { return }
}
} // End of notificationItem.reminder == true
} // End of notificationItem in items
} catch {
print("Local notification error")
} // End of catch
} // End of createLocalNotifications()
In case this is relevant, I also have an AppDelegate file with this code:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
} // End of func didFinishLaunchingWithOptions
} // End of AppDelegate
// Show local notification in foreground
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.list, .banner, .badge])
}
}