将Codable结构体存入UserDefaults后读取返回nil值的问题
解决自定义Codable对象存入UserDefaults后读取返回nil的问题
你遇到的读取时返回nil的问题,根源出在UserModel自定义的解码初始化方法里,我来帮你拆解问题并给出修复方案:
问题核心
在init(from decoder:)方法中,你解析userDetails的方式错误了:
// 错误写法 userDetails = try UserDetail(from: decoder)
你已经通过decoder.container(keyedBy:)获取了对应CodingKeys的容器,但却没有从这个容器里读取userDetails字段,反而直接把整个解码器传给UserDetail的初始化方法。这会让解码器尝试直接解码整个UserDetail结构,而非从userDetails这个键对应的字段中解析数据,最终导致解码失败,返回nil。
修复后的UserModel代码
把解码userDetails的代码改成从容器中读取对应键的值:
struct UserModel : Codable { var userDetails : UserDetail? var status : Bool? var message : String? enum CodingKeys: String, CodingKey { case userDetails = "userDetails" case status = "status" case message = "message" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) // 修正:从容器中解码userDetails字段 userDetails = try values.decodeIfPresent(UserDetail.self, forKey: .userDetails) status = try values.decodeIfPresent(Bool.self, forKey: .status) message = try values.decodeIfPresent(String.self, forKey: .message) } }
简化代码的建议
其实你的CodingKeys和结构体属性名完全一致,完全不需要手动定义CodingKeys和init(from decoder:)方法——Codable协议会自动生成默认的编码/解码逻辑,这样能避免手动编码带来的错误。简化后的代码更简洁:
struct UserModel : Codable { var userDetails : UserDetail? var status : Bool? var message : String? }
只要UserDetail也正确遵循Codable协议,这个版本的代码就能正常完成编码和解码工作。
额外小提示
在iOS 10及以后的版本中,UserDefaults.synchronize()已经被废弃,系统会自动处理数据同步,所以你保存数据的代码里可以去掉defaults.synchronize()这一行。
内容的提问来源于stack exchange,提问作者Zeeshan Suleman
相关产品推荐
相关产品推荐

