You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确将[Date: String]字典存入UserDefaults?编译报错求助

解决[Date: String]字典存入UserDefaults的问题

你遇到的错误根源是JSON不允许非字符串类型作为字典的键,直接用Date当key会导致JSONEncoder/JSONDecoder处理异常。下面是修正后的实现方案:

核心思路

把Date转换成标准字符串格式(比如ISO8601)作为字典key,存取时在Date和String之间做转换,避开JSON的键类型限制。

修正后的代码

// 扩展Date,实现和ISO字符串的双向转换
extension Date {
    func toISOString() -> String {
        ISO8601DateFormatter().string(from: self)
    }
    
    static func fromISOString(_ string: String) -> Date? {
        ISO8601DateFormatter().date(from: string)
    }
}

// 处理字典存取逻辑
guard let transDate = transDate else {
    // 先处理transDate为nil的情况,避免强制解包崩溃
    return
}

if let transData = UserDefaults.standard.data(forKey: "TransLedger") {
    print("UPDATE LEDGER")
    do {
        // 先解码成[String: String]格式(符合JSON要求)
        let oldStringDict = try JSONDecoder().decode([String: String].self, from: transData)
        // 转换成[Date: String]方便业务操作
        var oldDict: [Date: String] = [:]
        for (keyStr, value) in oldStringDict {
            if let date = Date.fromISOString(keyStr) {
                oldDict[date] = value
            }
        }
        // 更新字典内容
        oldDict[transDate] = productName
        
        // 再转换回[String: String]进行编码存储
        let newStringDict = oldDict.reduce(into: [String: String]()) { result, pair in
            result[pair.key.toISOString()] = pair.value
        }
        let newData = try JSONEncoder().encode(newStringDict)
        UserDefaults.standard.set(newData, forKey: "TransLedger")
    } catch {
        // 捕获编解码异常,不要用try!避免崩溃
        print("数据处理失败: \(error)")
    }
} else {
    // 首次存储的逻辑
    do {
        let newStringDict = [transDate.toISOString(): productName]
        let newData = try JSONEncoder().encode(newStringDict)
        UserDefaults.standard.set(newData, forKey: "TransLedger")
    } catch {
        print("首次存储失败: \(error)")
    }
}

关键改进点

  • 用ISO8601DateFormatter实现Date和String的双向转换,保证日期的唯一性和可解析性
  • 替换try!为do-catch捕获异常,避免编解码失败导致崩溃
  • 新增可选绑定处理transDate的nil情况,消除强制解包风险
  • 先将字典转换成[String: String]再进行JSON编解码,完全符合JSON的格式要求

内容的提问来源于stack exchange,提问作者RUSTAM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 19:35:03