You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS应用更新后本地通知无法持久送达问题排查

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:35:56