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
相关产品推荐
相关产品推荐

