iOS 10 User Notifications框架不支持间隔重复通知,如何实现?
实现iOS User Notifications框架的按间隔重复通知
嘿,这个问题我之前帮不少开发者踩过坑~iOS 10推出的User Notifications框架确实在「特定日期后按分钟/小时重复通知」这个需求上有点局限——原生的UNCalendarNotificationTrigger只支持天及以上的重复间隔,而UNTimeIntervalNotificationTrigger是从当前时间开始算间隔,没法直接指定一个起始日期后再循环触发。不过咱们可以用「接力触发」的思路来搞定,具体操作如下:
核心思路
先调度第一个在指定日期触发的通知,当这个通知被系统触发(无论用户是否点击),在通知的回调方法里,立刻调度下一个间隔X分钟/小时后的通知,以此实现循环重复的效果。
具体步骤&代码示例
1. 先请求通知权限
在使用通知前,必须先获取用户的授权:
import UserNotifications func requestNotificationPermission() { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in if granted { print("通知权限已获取") } else { print("通知权限被拒绝:\(error?.localizedDescription ?? "未知错误")") } } }
2. 调度第一个特定日期的通知
创建并添加第一个在目标日期触发的通知:
func scheduleFirstNotification(at targetDate: Date, repeatInterval: TimeInterval) { // 构建通知内容 let content = UNMutableNotificationContent() content.title = "重复提醒" content.body = "这是按间隔重复的通知内容" content.sound = UNNotificationSound.default // 把目标日期转成日期组件,用于创建日历触发器 let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: targetDate) let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false) // 创建通知请求(用唯一标识符区分) let request = UNNotificationRequest(identifier: "InitialRepeatNotification", content: content, trigger: trigger) // 添加到通知中心 UNUserNotificationCenter.current().add(request) { error in if let error = error { print("添加初始通知失败:\(error.localizedDescription)") } } }
3. 实现通知回调,接力触发下一个通知
首先让你的类(比如AppDelegate或者专门的通知管理类)遵守UNUserNotificationCenterDelegate,并设置代理:
// 在App启动时设置代理,比如在AppDelegate的didFinishLaunchingWithOptions里 UNUserNotificationCenter.current().delegate = self
然后实现回调方法,在通知触发后调度下一个重复通知:
// 处理用户点击通知的回调 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let requestID = response.notification.request.identifier // 判断当前通知是初始通知还是重复通知 if requestID == "InitialRepeatNotification" || requestID.hasPrefix("FollowUpRepeatNotification_") { // 设置重复间隔,比如30分钟(30*60秒) let interval: TimeInterval = 30 * 60 // 创建下一个通知的内容 let content = UNMutableNotificationContent() content.title = "重复提醒" content.body = "这是按间隔重复的通知内容" content.sound = UNNotificationSound.default // 创建时间间隔触发器 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: interval, repeats: false) // 生成唯一标识符,避免重复 let newRequestID = "FollowUpRepeatNotification_\(UUID().uuidString)" let newRequest = UNNotificationRequest(identifier: newRequestID, content: content, trigger: trigger) // 添加下一个通知 center.add(newRequest) { error in if let error = error { print("添加重复通知失败:\(error.localizedDescription)") } } } completionHandler() } // 如果需要在App前台也显示通知,实现这个方法 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound]) }
额外补充
- 如果需要应用重启后继续重复逻辑,可以用
UserDefaults记录最后一次触发通知的时间,在App启动时计算下一个触发时间,重新添加通知。 - 这种「接力」方式的好处是不会一次性添加大量通知,避免触发系统的通知数量限制;但如果用户关闭了通知权限,后续的通知就无法触发了,所以要做好权限状态的监听。
内容的提问来源于stack exchange,提问作者Duy Tư




