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

iOS平台UNUserNotificationCenter条件化重复通知调度及限制问题

iOS重复本地通知实现与批量任务处理指南

嘿,我来帮你理清楚iOS重复本地通知的实现思路,还有100个任务批量处理的方案~

一、三种重复场景的具体实现

iOS的UserNotifications框架里,UNCalendarNotificationTrigger是实现按日期/周/月重复通知的核心,下面分场景给你具体代码和注意事项:

1. 每日推送直至指定日期

创建一个匹配固定时分的日历触发器,设置重复为true,但系统不会自动终止,所以需要我们手动检查截止日期并清理通知。

// 1. 构建通知内容
let content = UNMutableNotificationContent()
content.title = "任务提醒"
content.body = "记得检查任务完成情况哦"
content.sound = UNNotificationSound.default

// 2. 设置每日触发的时间(比如早上9点)
var dateComponents = DateComponents()
dateComponents.hour = 9
dateComponents.minute = 0

// 3. 创建重复触发器
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)

// 4. 生成唯一标识符(建议关联任务ID,方便后续管理)
let taskId = "123" // 替换为你的任务唯一ID
let requestIdentifier = "daily_task_\(taskId)"

// 5. 创建并添加通知请求
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
    if let error = error {
        print("添加每日通知失败: \(error.localizedDescription)")
    }
}

终止逻辑:当APP启动、用户点击通知,或者任务截止日期到达时,遍历待处理通知,移除超过截止日的请求:

UNUserNotificationCenter.current().getPendingNotificationRequests { requests in
    let expiredIdentifiers = requests.filter { request in
        // 根据request的identifier解析对应的任务,检查是否过期
        let taskId = request.identifier.replacingOccurrences(of: "daily_task_", with: "")
        guard let task = yourTaskManager.getTask(withId: taskId) else { return true }
        return Date() > task.endDate
    }.map { $0.identifier }
    
    UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: expiredIdentifiers)
}

2. 每周一推送直至指定日期

和每日逻辑类似,只需要在DateComponents里指定weekday(注意iOS中weekday=1是周日,2是周一):

var dateComponents = DateComponents()
dateComponents.weekday = 2 // 周一
dateComponents.hour = 9
dateComponents.minute = 0

let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let requestIdentifier = "weekly_task_\(taskId)"
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)

终止逻辑和每日场景一致,只需对应修改标识符的前缀即可。

3. 每月指定日期推送直至指定日期

设置DateComponents的day字段为你需要的日期(比如每月15号),注意如果当月没有该日期(比如2月没有30号),系统会自动调整到当月最后一天触发:

var dateComponents = DateComponents()
dateComponents.day = 15 // 每月15号
dateComponents.hour = 9
dateComponents.minute = 0

let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let requestIdentifier = "monthly_task_\(taskId)"
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)

终止逻辑同样参考每日场景,检查任务截止日期后清理无效通知。

二、单个APP的通知数量限制与100个任务的处理方案

关于通知数量限制

iOS官方没有明确限制单个APP的待处理通知请求数量,但实际测试中,100个完全在系统承载范围内,不会有性能问题。如果数量达到几千级,可能会出现系统优化清理的情况,但100个完全不用担心。

100个任务的批量处理技巧

  • 统一标识符规范:给每个通知请求设置唯一且可解析的标识符,比如"{repeatType}_task_{taskId}",这样能快速关联到对应的任务,方便后续查找、修改或删除。
  • 避免重复添加:在添加新通知前,先检查是否已有相同标识符的待处理请求,避免重复调度:
UNUserNotificationCenter.current().getPendingNotificationRequests { requests in
    let existingIds = requests.map { $0.identifier }
    let targetId = "daily_task_123"
    if existingIds.contains(targetId) {
        UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [targetId])
    }
    // 再添加新的通知请求
}
  • 批量清理无效通知:APP启动时统一检查所有待处理通知,移除已完成、过期的任务对应的通知,保持通知列表的整洁。
  • 任务状态联动:当任务完成、截止日期修改或被删除时,立即移除对应的通知请求,避免无效通知打扰用户。

三、额外注意事项

  • 权限检查:确保已经通过UNUserNotificationCenter.current().requestAuthorization()获取了用户的通知权限(包括alert、sound等),否则通知无法推送。
  • 时区适配:DateComponents默认使用用户当前时区,如果需要固定时区(比如服务器时区),可以设置dateComponents.timeZone = TimeZone(identifier: "Asia/Shanghai")。
  • 后台处理:如果APP在后台,通知触发时可以通过UNUserNotificationCenterDelegate的userNotificationCenter(_:didReceive:withCompletionHandler:)方法处理,此时可以检查任务状态,决定是否继续调度或清理通知。

内容的提问来源于stack exchange,提问作者A.s.ALI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:16:23