无法初始化nil Date:iOS App首次运行JSON更新失败问题排查
问题
- 用于标记JSON更新时间的
storedDate初始化存在异常:App首次运行时无法触发JSON更新,后续更新流程正常。为触发首次启动的即时更新,尝试将初始日期设为旧日期,但该逻辑从未生效。 - 不愿使用可选
Date配合??的处理方式(需在多处编写合并逻辑,且编造默认日期不符合编码规范),希望找到更优的Date初始化方案。 - 调试发现:首次运行且UserDefaults中无存储日期时,进入初始化器前
storedDate已被设为当前日期,设置旧日期的逻辑未被执行。 - 初始化器中
let storedDate = UserDefaults...行出现「未使用变量」警告,但明明在逻辑中用到了该变量,不知如何消除警告。
解决方案
问题根源
- 局部变量遮蔽类属性:初始化器中定义的
let storedDate是局部变量,并未给类的storedDate属性赋值,导致类属性始终保持默认的当前日期;局部变量后续未被实际使用,因此触发警告。 - 类属性提前初始化:类的
storedDate属性设置了默认值Date(),在初始化器执行前就已完成赋值,覆盖了初始化器中的自定义逻辑。
修复步骤
- 移除类属性的默认值,在初始化器中直接为类的
storedDate属性赋值。 - 避免定义局部变量
storedDate,直接操作类属性,同时同步到UserDefaults。 - 使用安全的可选绑定读取UserDefaults中的日期,避免强制解包引发崩溃。
修正后的代码
@Observable final class GetRatesModel { @ObservationIgnored var storedDate: Date // 移除默认值 init() { // 安全读取UserDefaults中的日期 if let savedDate = UserDefaults.standard.object(forKey: StorageKeys.upd.rawValue) as? Date { self.storedDate = savedDate } else { // 首次启动时设置前一天的日期,比硬编码时间戳更清晰可靠 let oldDate = Calendar.current.date(byAdding: .day, value: -1, to: Date.now)! self.storedDate = oldDate UserDefaults.standard.setValue(oldDate, forKey: StorageKeys.upd.rawValue) } } @MainActor func checkForUpdates(baseCur: String) async throws { // 比较日期是否为同一天 if !Calendar.current.isDate(Date.now, equalTo: storedDate, toGranularity: .day) { print("getting data") let stored8601 = storedDate.formatted(.iso8601.year().month().day().dateSeparator(.dash)) if stored8601 != JsonDate { // 更新日期时同步类属性和UserDefaults self.storedDate = Date.now UserDefaults.standard.setValue(self.storedDate, forKey: StorageKeys.upd.rawValue) // ... 后续JSON更新逻辑 } } } }
额外说明
- 在
checkForUpdates方法中更新日期时,需同时修改类的storedDate属性和UserDefaults,保证两者状态同步。 - 用
Calendar生成旧日期比硬编码时间戳更易读,也能避免因时间单位(秒/毫秒)误解导致的逻辑错误。
内容的提问来源于stack exchange,提问作者Galen Smith
相关产品推荐
相关产品推荐

