1. 核心方法
使用 UNCalendarNotificationTrigger
的 dateMatching
参数配置日历组件(DateComponents
),结合 repeats: true
实现周期性触发。
2. 不同频率的重复推送配置
2.1 每日重复
每天固定时间触发(如上午 10:00):
var components = DateComponents()
components.hour = 10 // 小时(24 小时制)
components.minute = 0 // 分钟
let trigger = UNCalendarNotificationTrigger(
dateMatching: components,
repeats: true
)
2.2 每周重复
每周特定星期几触发(如每周五下午 3:00):
var components = DateComponents()
components.weekday = 6 // 1=周日, 2=周一...6=周五, 7=周六
components.hour = 15
components.minute = 0
let trigger = UNCalendarNotificationTrigger(
dateMatching: components,
repeats: true
)
2.3 每月重复
每月特定日期触发(如每月 15 日上午 9:00):
var components = DateComponents()
components.day = 15 // 每月 15 日
components.hour = 9
components.minute = 0
let trigger = UNCalendarNotificationTrigger(
dateMatching: components,
repeats: true
)
2.4 每年重复
每年特定日期触发(如每年 12 月 25 日 8:00):
var components = DateComponents()
components.month = 12 // 12 月
components.day = 25 // 25 日
components.hour = 8
components.minute = 0
let trigger = UNCalendarNotificationTrigger(
dateMatching: components,
repeats: true
)
2.5 自定义间隔重复
通过 UNTimeIntervalNotificationTrigger
实现固定间隔重复(如每隔 2 小时):
// 注意:repeats 为 true 时,timeInterval 必须 ≥ 60 秒
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: 7200, // 2 小时 = 60*60*2 秒
repeats: true
)
3. 完整代码示例(SwiftUI 中实现)
以下示例展示如何创建一个允许用户选择重复频率(每日、每周、每月)的通知功能。
import SwiftUI
import UserNotifications
struct RepeatingNotificationView: View {
// 用户选择的重复类型
enum RepeatType: String, CaseIterable {
case daily = "每日"
case weekly = "每周"
case monthly = "每月"
}
@State private var selectedRepeat: RepeatType = .daily
@State private var notificationTime = Date()
@State private var showAlert = false
@State private var alertMessage = ""
var body: some View {
Form {
// 选择重复类型
Picker("重复频率", selection: $selectedRepeat) {
ForEach(RepeatType.allCases, id: \.self) { type in
Text(type.rawValue)
}
}
// 选择时间
DatePicker("提醒时间", selection: $notificationTime, displayedComponents: .hourAndMinute)
Button("保存提醒") {
scheduleRepeatingNotification()
}
}
.alert("提示", isPresented: $showAlert) {
Button("确定") { }
} message: {
Text(alertMessage)
}
}
// 调度重复通知
private func scheduleRepeatingNotification() {
let content = UNMutableNotificationContent()
content.title = "\(selectedRepeat.rawValue)提醒"
content.body = "这是您的\(selectedRepeat.rawValue)提醒!"
content.sound = .default
// 根据用户选择生成触发器
let trigger: UNCalendarNotificationTrigger = {
let components = Calendar.current.dateComponents(
[.hour, .minute, .weekday, .day],
from: notificationTime
)
var triggerComponents = DateComponents()
switch selectedRepeat {
case .daily:
triggerComponents.hour = components.hour
triggerComponents.minute = components.minute
case .weekly:
triggerComponents.weekday = components.weekday
triggerComponents.hour = components.hour
triggerComponents.minute = components.minute
case .monthly:
triggerComponents.day = components.day
triggerComponents.hour = components.hour
triggerComponents.minute = components.minute
}
return UNCalendarNotificationTrigger(
dateMatching: triggerComponents,
repeats: true
)
}()
// 创建并添加通知请求
let identifier = "\(selectedRepeat.rawValue)_\(Date().timeIntervalSince1970)"
let request = UNNotificationRequest(
identifier: identifier,
content: content,
trigger: trigger
)
UNUserNotificationCenter.current().add(request) { error in
DispatchQueue.main.async {
if let error = error {
alertMessage = "添加失败: \(error.localizedDescription)"
} else {
alertMessage = "\(selectedRepeat.rawValue)提醒已设置!"
}
showAlert = true
}
}
}
}
4. 关键注意事项
-
标识符管理
- 使用唯一
identifier
(如结合时间戳),避免重复通知被覆盖。 - 示例:
let identifier = "weekly_\(UUID().uuidString)"
。
- 使用唯一
-
时区处理
- 默认使用系统时区,可通过
components.timeZone
指定特定时区:triggerComponents.timeZone = TimeZone(identifier: "Asia/Shanghai")
- 默认使用系统时区,可通过
-
用户权限
- 确保已授权通知权限(
UNUserNotificationCenter.current().getNotificationSettings
)。
- 确保已授权通知权限(
-
重复限制
UNTimeIntervalNotificationTrigger
的重复间隔必须 ≥ 60 秒。- 日历触发器的
dateMatching
必须包含足够字段(如每周重复需设置weekday
)。
-
前台通知处理
- 应用在前台时默认不显示通知,需实现
UNUserNotificationCenterDelegate
:func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions { return [.banner, .sound] }
- 应用在前台时默认不显示通知,需实现
5. 应用场景示例
- 每日提醒:早晨 7 点喝水提醒。
- 每周提醒:每周五下午 5 点提交工作报告。
- 每月提醒:每月 1 日缴纳房租。
- 自定义间隔:每隔 2 小时提醒休息(需
UNTimeIntervalNotificationTrigger
)。
总结
- 核心类:
UNCalendarNotificationTrigger
+DateComponents
实现灵活重复规则。 - 用户体验:通过 SwiftUI 表单让用户自定义频率和时间。
- 最佳实践:合理管理通知标识符,避免重复或无效通知。
通过合理设计重复通知逻辑,可以满足大部分周期性提醒需求,同时保持代码简洁和可维护性。