iOS应用更新后本地通知无法持久送达问题排查
我有一款上架App Store的iOS应用,支持根据用户需求调度本地通知。近期发现应用自动更新后,之前已调度的本地通知无法送达。用户本应收到通知后再启动应用,但现在必须重启应用重新调度,完全违背了产品核心价值。
苹果官方表示应用更新后本地通知应正常触发,保障无缝更新体验,但我的应用确实存在这个问题,非更新场景下通知完全正常。现在需要排查是我的通知调度逻辑导致更新后无法持久,还是其他原因。
以下是应用进入后台阶段时执行的本地通知调度代码:
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()
问题排查方向
缺少启动阶段的通知重调度逻辑:当前代码仅在应用进入后台时执行通知调度,但应用自动更新后,用户未手动打开应用的情况下,系统不会触发后台回调,导致没有机会重新生成通知。即便苹果官方称更新后pending通知会保留,但实际测试中存在一次性通知被意外清除的案例。建议在应用启动入口(如
application(_:didFinishLaunchingWithOptions:)或SceneDelegate的scene(_:willConnectTo:options:))中也调用createLocalNotifications(),确保更新后首次启动就能同步通知。Trigger时区未显式设置:当前构造
triggerDate时未指定时区,默认使用系统当前时区。如果用户更新应用时跨时区切换,可能导致触发时间解析异常。建议补充时区设置:triggerDate.timeZone = Calendar.current.timeZone验证pending通知的存活状态:在应用启动时添加调试代码,查看更新后是否还有留存的pending通知:
UNUserNotificationCenter.current().getPendingNotificationRequests { requests in print("Pending notifications count after launch: \(requests.count)") }如果结果为0,说明系统确实清除了旧通知,此时必须在启动时重新调度。
检查应用更新时的运行状态:如果应用在更新时处于后台活跃状态,系统可能会强制杀死进程并清除pending通知,这种场景下同样需要启动时重新同步通知。
内容的提问来源于stack exchange,提问作者ej5607

