当前位置: 首页 > news >正文

7.2 重复推送(每日、每周等)

1. 核心方法

使用 UNCalendarNotificationTriggerdateMatching 参数配置日历组件(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. 关键注意事项

  1. 标识符管理

    • 使用唯一 identifier(如结合时间戳),避免重复通知被覆盖。
    • 示例:let identifier = "weekly_\(UUID().uuidString)"
  2. 时区处理

    • 默认使用系统时区,可通过 components.timeZone 指定特定时区:
      triggerComponents.timeZone = TimeZone(identifier: "Asia/Shanghai")
      
  3. 用户权限

    • 确保已授权通知权限(UNUserNotificationCenter.current().getNotificationSettings)。
  4. 重复限制

    • UNTimeIntervalNotificationTrigger 的重复间隔必须 ≥ 60 秒。
    • 日历触发器的 dateMatching 必须包含足够字段(如每周重复需设置 weekday)。
  5. 前台通知处理

    • 应用在前台时默认不显示通知,需实现 UNUserNotificationCenterDelegate
      func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
          return [.banner, .sound]
      }
      

5. 应用场景示例

  • 每日提醒:早晨 7 点喝水提醒。
  • 每周提醒:每周五下午 5 点提交工作报告。
  • 每月提醒:每月 1 日缴纳房租。
  • 自定义间隔:每隔 2 小时提醒休息(需 UNTimeIntervalNotificationTrigger)。

总结

  • 核心类UNCalendarNotificationTrigger + DateComponents 实现灵活重复规则。
  • 用户体验:通过 SwiftUI 表单让用户自定义频率和时间。
  • 最佳实践:合理管理通知标识符,避免重复或无效通知。

通过合理设计重复通知逻辑,可以满足大部分周期性提醒需求,同时保持代码简洁和可维护性。

相关文章:

  • springboot集成kafka,后续需要通过flask封装restful接口
  • 基于 Node.js 和 Spring Boot 的 RSA 加密登录实践
  • 程序化广告行业(70/89):ABTester系统助力落地页优化实践
  • 【C++篇】深入解析C/C++内存管理:从原理到实践
  • c语言 文件操作
  • MTO和MTS不同模式制造业数字化转型的“三座大山“:MES/ERP/PLM系统集成技术全解析
  • Buffer Pool 的核心作用与工作机制
  • uni-app使用web-view传参的坑
  • HOW - React Error Catch 机制
  • Three.js 系列专题 7:性能优化与最佳实践
  • TVBOX最新配置接口\直播源接口 收集整理【 2025.4】
  • Token无感刷新
  • 蓝桥杯备赛 Day 21 图论基础
  • 拼多多商品详情接口爬虫实战指南
  • 多线程代码案例(线程池)- 4
  • Rust 之四 运算符、标量、元组、数组、字符串、结构体、枚举
  • springboot Filter实现请求响应全链路拦截!完整日志监控方案​​
  • DeepSeek底层揭秘——《推理时Scaling方法》技术对比浅析
  • AI日报 - 2025年4月9日
  • 信息系统项目管理师-第十三章-项目资源管理
  • 上海145家博物馆、73家美术馆将减免费开放
  • 王毅谈中拉命运共同体建设“五大工程”及落实举措
  • 在地球另一端的交流,架起2万公里间更多共赢的桥梁
  • 重庆一高校75万采购市价299元产品?工作人员:正在处理
  • 技术派|巴基斯坦导弹:让印度保持克制的“定海神针”?
  • 普京提议于15日在土耳其恢复俄乌直接谈判