如何为UserDefaults设置过期时间?附现有存取实现代码
给UserDefaults的存储内容添加过期时间功能
嘿,这个需求我之前做项目的时候也碰到过,其实核心逻辑很清晰:存值的时候顺便记录过期时间戳,读值的时候对比当前时间判断是否失效。下面是基于你现有代码改造的完整方案:
1. 改造存储方法:支持传入过期时长
我们把要存的值和对应的过期时间打包成一个字典存储,这样读取时能一次性拿到判断依据:
static func _setByKey(_ key: String, _ val: Any, expirationSeconds: TimeInterval) { // 计算过期时间戳:当前时间 + 设定的过期秒数 let expirationTimestamp = Date().timeIntervalSince1970 + expirationSeconds // 封装成字典存储 let storedData: [String: Any] = [ "storedValue": val, "expiresAt": expirationTimestamp ] UserDefaults.standard.set(storedData, forKey: key) }
如果需要默认的过期时长(比如默认24小时过期),可以加个重载方法,保持和你原有方法的调用习惯一致:
static func _setByKey(_ key: String, _ val: Any) { // 默认86400秒 = 24小时 _setByKey(key, val, expirationSeconds: 86400) }
2. 改造读取方法:自动判断并清理过期数据
读取时先取出存储的字典,对比当前时间和过期时间戳,一旦发现过期就清理掉这个键并返回nil:
static func _getByKey(_ key: String) -> Any? { // 先取出存储的字典,格式不对直接返回nil guard let storedDict = UserDefaults.standard.dictionary(forKey: key), let targetValue = storedDict["storedValue"], let expiresTimestamp = storedDict["expiresAt"] as? TimeInterval else { return nil } let currentTime = Date().timeIntervalSince1970 if currentTime > expiresTimestamp { // 数据已过期,清理无效条目 UserDefaults.standard.removeObject(forKey: key) return nil } // 数据有效,返回存储的值 return targetValue }
3. 可选优化:批量清理所有过期数据
如果你的App里存了很多带过期时间的键,可以加个方法定期清理(比如在App启动时调用):
static func cleanAllExpiredEntries() { let allStoredKeys = UserDefaults.standard.dictionaryRepresentation().keys for key in allStoredKeys { // 调用读取方法,自动触发过期清理 _ = _getByKey(key) } }
小提醒
- 上面的方案兼容String、Int、Bool这些基础类型,如果要存自定义对象,记得先把对象转成遵循
Codable的Data再存储。 - 过期判断依赖设备本地时间,如果用户手动修改系统时间,可能会导致判断逻辑异常,这点需要根据你的业务场景评估是否要做额外处理。
内容的提问来源于stack exchange,提问作者Trần Hữu Hiền
相关产品推荐
相关产品推荐

