如何在指定起始日期后重复发送iOS本地通知?
问题解答
核心疑问解答
如果给dateComponents同时设置年、月、日、时、分参数,且repeats=true,系统只会触发一次通知。原因是:
UNCalendarNotificationTrigger的重复逻辑依赖「周期性时间模式」,比如每日、每周、每年重复。- 当你指定固定的年、月、日时,这个时间点是唯一的,后续日期无法匹配所有参数(比如下一年的年份和指定年份不一致),因此触发器只会在指定的年月日时分触发一次,不会重复。
实现「从指定起始日期开始每日重复通知」的正确方案
你的需求是让通知从指定起始日期的时分开始,之后每日同一时间触发,不能提前触发。直接用带年月日的重复触发器无法实现,推荐分两步处理:
方案逻辑
- 第一次通知:创建一个非重复的触发器,精准匹配起始日期的年、月、日、时、分,确保第一次通知在指定日期触发。
- 后续重复通知:在起始日期之后,创建一个仅包含时、分参数的重复触发器,实现每日同一时间通知。
代码实现
func addDailyNotificationStartingFrom(text: String, startDate: Date, id: String) { let currentDate = Date() let content = UNMutableNotificationContent() // 配置通知内容 content.title = "My App" content.body = text content.sound = .default content.badge = NSNumber(integerLiteral: UIApplication.shared.applicationIconBadgeNumber + 1) if startDate > currentDate { // 1. 添加起始日期的单次通知 let firstDateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: startDate) let firstTrigger = UNCalendarNotificationTrigger(dateMatching: firstDateComponents, repeats: false) let firstRequest = UNNotificationRequest(identifier: "\(id)_first", content: content, trigger: firstTrigger) UNUserNotificationCenter.current().add(firstRequest) { error in if let error = error { print(error.localizedDescription) } } // 2. 添加从起始日期次日开始的每日重复通知 guard let nextDayDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate) else { return } let repeatDateComponents = Calendar.current.dateComponents([.hour, .minute], from: nextDayDate) let repeatTrigger = UNCalendarNotificationTrigger(dateMatching: repeatDateComponents, repeats: true) let repeatRequest = UNNotificationRequest(identifier: id, content: content, trigger: repeatTrigger) UNUserNotificationCenter.current().add(repeatRequest) { error in if let error = error { print(error.localizedDescription) } } } else { // 起始日期已过,直接添加每日重复通知(下一次触发为次日的指定时分) let repeatDateComponents = Calendar.current.dateComponents([.hour, .minute], from: startDate) let repeatTrigger = UNCalendarNotificationTrigger(dateMatching: repeatDateComponents, repeats: true) let repeatRequest = UNNotificationRequest(identifier: id, content: content, trigger: repeatTrigger) UNUserNotificationCenter.current().add(repeatRequest) { error in if let error = error { print(error.localizedDescription) } } } }
代码说明
- 先判断起始日期是否在当前时间之后:
- 若起始日期在未来:先触发一次指定日期的通知,再从次日开始每日重复。
- 若起始日期已过:直接启动每日重复通知,下一次触发为次日的指定时分。
- 用不同的
identifier区分单次通知和重复通知,方便后续管理(比如取消通知)。
内容的提问来源于stack exchange,提问作者Hugo Silva
相关产品推荐
相关产品推荐

