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

Swift实现每5天上午10点重复本地通知的问题排查

解决每5天上午10点重复发送UNLocalNotification的问题

Hey,我来帮你搞定这个重复通知的问题!你的代码没生效主要是因为没用到正确的重复触发器,而且日期组件的设置不够完整,没法实现每5天重复的逻辑。下面是完整的解决方案:

1. 先搞定通知权限(必做前提)

没有通知权限的话,不管怎么设置通知都发不出来,所以第一步一定要请求权限:

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
    if let error = error {
        print("请求通知权限出错:\(error.localizedDescription)")
        return
    }
    if granted {
        print("通知权限已授权,可以继续设置通知")
    } else {
        print("用户拒绝了通知权限,需要引导用户到系统设置开启")
    }
}

2. 创建通知内容

这部分你原来的代码没问题,我稍微优化了一下细节:

let content = UNMutableNotificationContent()
content.title = "Hello!"
content.body = "Hello_message_body"
content.sound = UNNotificationSound.default
// 如果需要显示应用角标,可以加这句,不需要就删掉
content.badge = 1

3. 计算第一次触发的准确日期(5天后的上午10点)

这里要确保日期组件的完整性,不能只设置小时,得把年月日时分秒都处理好,避免出现日期错误:

let calendar = Calendar.current
calendar.timeZone = TimeZone.current

// 获取当前日期的完整组件
var fireComponents = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: Date())
// 给当前日期加5天
fireComponents.day! += 5
// 固定触发时间为上午10点整
fireComponents.hour = 10
fireComponents.minute = 0
fireComponents.second = 0

// 构造出准确的第一次触发日期
guard let firstFireDate = calendar.date(from: fireComponents) else {
    print("无法构造正确的触发日期,请检查组件设置")
    return
}

4. 创建重复触发器(关键!)

根据你支持的iOS版本,分两种情况:

情况一:支持iOS 15及以上

iOS 15新增了带初始触发日期的时间间隔触发器,能直接指定第一次触发时间,同时设置每5天重复,非常方便:

// 每5天的时间间隔:5天 × 24小时 × 60分钟 × 60秒
let repeatInterval: TimeInterval = 5 * 24 * 60 * 60
// 创建触发器:指定初始触发日期 + 每5天重复
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: repeatInterval, repeats: true, initialFireDate: firstFireDate)

情况二:兼容iOS 15以下

需要先计算当前时间到第一次触发日期的间隔,再创建触发器,确保第一次触发后每5天重复:

let repeatInterval: TimeInterval = 5 * 24 * 60 * 60
let timeUntilFirstFire = firstFireDate.timeIntervalSinceNow

// 确保触发时间在未来,避免设置过去的时间
guard timeUntilFirstFire > 0 else {
    print("设置的触发时间已过期,请调整日期(比如把day+6)")
    return
}

// 创建触发器:第一次在timeUntilFirstFire后触发,之后每5天重复
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeUntilFirstFire + repeatInterval, repeats: true)

5. 添加通知请求到通知中心

最后给通知一个唯一ID,方便后续修改或删除,然后添加到通知中心:

// 唯一标识符,用于后续管理这个通知(比如删除、更新)
let requestID = "FiveDayMorningReminder"
let request = UNNotificationRequest(identifier: requestID, content: content, trigger: trigger)

// 添加请求到通知中心
UNUserNotificationCenter.current().add(request) { error in
    if let error = error {
        print("添加通知请求失败:\(error.localizedDescription)")
    } else {
        print("通知设置成功!首次触发时间:\(firstFireDate),之后每5天上午10点重复")
    }
}

额外提醒

  • 如果用户手动关闭了通知权限,或者在系统设置里删除了这个通知,它就不会再触发了,建议在APP启动时检查权限状态和通知是否存在。
  • 你原来的代码只设置了小时组件,没有处理完整的年月日,也没有创建重复触发器,这就是通知没生效的核心原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:38:48