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

iOS Swift多本地通知调度问题:隔日报药提醒触发异常求助

解决iOS用药提醒APP隔日通知无法触发的问题

问题根源

  1. 日期组件不完整:你的getDateComponents()方法只提取了小时、分钟、秒和日,缺少年份和月份。UNCalendarNotificationTrigger创建一次性通知时,仅指定日会导致系统无法定位到具体某一天(会匹配每个月的对应日期),后续通知的触发器并没有指向你预期的日期。
  2. 循环终止逻辑错误:循环内的guard let date = ... else {return}会在某次日期计算失败时直接终止整个函数,导致后续所有通知都无法创建,应该改为continue跳过当前错误项。
  3. 冗余的通知分类设置:每次调用scheduleNotification都重复设置通知分类,虽然不影响功能,但属于不必要的重复操作,建议移到App启动时初始化一次。

修复代码

1. 修正日期组件提取方法

extension Date {
    public func getDateComponents() -> DateComponents {
        // 补充年份和月份,确保触发器能准确定位到具体某天
        return Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: self)
    }
}

2. 修正隔日通知的循环逻辑

else if notification.frequency == .alternateDay {
    let firstDate = notification.date
    for i in stride(from: 0, to: 30, by: 2) {
        guard let date = Calendar.current.date(byAdding: .day, value: i, to: firstDate) else {
            // 跳过当前错误的日期,继续创建后续通知
            continue
        }
        let dateComponents = date.getDateComponents()
        print(date)
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
        let request = UNNotificationRequest(
            identifier: notification.id + String(i),
            content: content,
            trigger: trigger)
        // 添加错误处理,排查单个通知创建失败的情况
        UNUserNotificationCenter.current().add(request) { error in
            if let error = error {
                print("通知创建失败: \(error.localizedDescription)")
            }
        }
    }
    self.getPendingRequests()
}

3. 优化通知分类初始化(可选)

将通知分类的设置移到App启动流程中,避免重复执行:

// 在AppDelegate或SceneDelegate的启动方法中添加
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 初始化通知分类
    let takenAction = UNNotificationAction(identifier: Constants.notiTakenActionIdentifier, title: Constants.notificationTakenText)
    let notTakenAction = UNNotificationAction(identifier: Constants.notiNotTakenActionIdentifier, title: Constants.notificationNotTakenText)
    let actionCategory = UNNotificationCategory(identifier: Constants.notificaitonCategoryIdentifier, actions: [takenAction, notTakenAction], intentIdentifiers: [])
    UNUserNotificationCenter.current().setNotificationCategories([actionCategory])
    
    return true
}

测试提示

  • 修改系统日期后,需要重启App才能让通知触发器正确识别新日期(iOS系统限制)。
  • 调用UNUserNotificationCenter.current().getPendingNotificationRequests打印所有待触发通知,确认每个隔日通知的触发日期是否符合预期。

内容的提问来源于stack exchange,提问作者Venkatesh Chejarla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:40:24