Swift iOS不用NSTimer实现满一周增变量、检测用户活跃并推送的方案咨询
iOS 跨进程时间追踪及周度触发方案
NSTimer 依赖应用进程存活,应用被杀死、进入后台超过系统保活时长后都会失效,完全不适合跨周度的时间追踪需求,下面是可落地的无NSTimer实现方案:
1. 周度变量自增逻辑实现
核心思路是用本地持久化存储关键时间戳,每次应用激活时做差值校验:
- 用
UserDefaults或沙盒文件持久化两个时间戳:上次执行周度自增的时间、上次应用启动的时间 - 在应用启动回调
didFinishLaunchingWithOptions、从后台激活回调applicationDidBecomeActive中分别触发校验逻辑 - 时间差计算优先使用系统日历API,避免时区、夏令时、闰秒导致的计算误差,Swift示例代码如下:
// 读取上次周更时间 let lastUpdateDate = UserDefaults.standard.object(forKey: "LastWeeklyUpdateDate") as? Date ?? Date() let calendar = Calendar.current // 计算两个日期的间隔天数 let intervalDays = calendar.dateComponents([.day], from: lastUpdateDate, to: Date()).day ?? 0 if intervalDays >= 7 { // 执行指定变量自增逻辑 targetCount += 1 // 更新本次周更时间到本地 UserDefaults.standard.set(Date(), forKey: "LastWeeklyUpdateDate") } // 每次激活都更新上次启动时间 UserDefaults.standard.set(Date(), forKey: "LastAppLaunchDate")
2. 一周未启动推送提醒实现
该需求完全不需要应用后台存活,直接用系统本地推送能力即可实现:
- 首先需要在应用首次启动时向用户申请通知权限,权限通过后才能正常推送
- 每次应用激活时,先取消之前调度的未触发的周度提醒推送,再重新调度一个7天后触发的推送
- 逻辑说明:如果用户7天内打开过应用,推送触发时间会被不断延后7天;如果用户始终未打开,系统会在7天后自动弹出预设提醒,Swift示例代码如下:
let notifyCenter = UNUserNotificationCenter.current() // 取消之前的同类型待触发推送 notifyCenter.removePendingNotificationRequests(withIdentifiers: ["WeeklyOpenReminder"]) // 构造推送内容 let content = UNMutableNotificationContent() content.title = "好久不见" content.body = "你已经一周没打开应用啦,快来看看新内容~" content.sound = .default // 设置7天后触发 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 7 * 24 * 3600, repeats: false) let request = UNNotificationRequest(identifier: "WeeklyOpenReminder", content: content, trigger: trigger) notifyCenter.add(request)
注意事项
- 不要用设备开机时长、进程运行时长做计算基准,用户重启设备、杀进程都会导致数据重置,必须用系统真实时间戳
- 如果担心用户手动修改系统时间作弊,可以在应用联网时同步服务器时间做校验,纯本地场景用系统时间可以覆盖绝大多数正常用户需求
- 本地推送只有在用户同意通知权限后才能正常触发,需要做好权限申请引导和权限未开启的兼容处理
内容的提问来源于stack exchange,提问作者Kiran Lim
相关产品推荐
相关产品推荐

