You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

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ư

火山引擎 最新活动