将 Decodable 结构存储到 Userdefaults

Posted

技术标签:

【中文标题】将 Decodable 结构存储到 Userdefaults【英文标题】:Store Decodable struct to Userdefaults 【发布时间】:2018-01-11 13:10:35 【问题描述】:

我有一个像这样的Decodable 结构......

struct BestWishes: Decodable 

    private enum CodingKeys : String, CodingKey 
        case customerID = "customer_id"
        case birthDate = "birth_date"
         case type = "type"
        case customerName = "customer_name"
        case mobileNo = "mobile_number"
    
    let customerID: Int
    let date: String
    let type: String
    let customerName : String
    let mobileNumber: Int

    public init(from decoder: Decoder) throws 
        let container = try decoder.container(keyedBy: CodingKeys.self)
        customerID = try container.decode(Int.self, forKey: .customerID)
        type = try container.decode(String.self, forKey: .type)
        if type == "anniversary_date" 
            date = try container.decode(String.self, forKey: .anniversaryDate)
         else 
            date = try container.decode(String.self, forKey: .birthDate)
        
        customerName = try container.decode(String.self, forKey: .customerName)
        mobileNumber = try container.decode(Int.self, forKey: .mobileNo)
    

并且其中的所有数据都存储在这样的数组中..

var bestWishesArr = [BestWishes]()
self.bestWishesArr.append(contentsOf: result.bestWishes) 

现在我想将bestWishesArr 存储到 Userdefaults。不知道如何实现...

【问题讨论】:

使用keyarchiver。请参考以下***.com/a/37983027/1142743 不,@Vinodh 它似乎不起作用。我的结构是 Decodable 类型的 有可能然后你接受了答案。在不知道/尝试任何事情的情况下,不要说这是不可能的 【参考方案1】:

添加Codable 协议的后半部分。为了与init 方法兼容,date 属性的保存方式因type 而不同

struct BestWish: Codable 

    private enum CodingKeys : String, CodingKey 
        case customerID = "customer_id"
        case birthDate = "birth_date"
        case anniversaryDate = "anniversary_date"
        case type
        case customerName = "customer_name"
        case mobileNumber = "mobile_number"
    
    let customerID: Int
    let date: String
    let type: String
    let customerName : String
    let mobileNumber: Int

    public init(from decoder: Decoder) throws 
        let container = try decoder.container(keyedBy: CodingKeys.self)
        customerID = try container.decode(Int.self, forKey: .customerID)
        type = try container.decode(String.self, forKey: .type)
        if type == "anniversary_date" 
            date = try container.decode(String.self, forKey: .anniversaryDate)
         else 
            date = try container.decode(String.self, forKey: .birthDate)
        
        customerName = try container.decode(String.self, forKey: .customerName)
        mobileNumber = try container.decode(Int.self, forKey: .mobileNumber)
    

    func encode(to encoder: Encoder) throws 
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(customerID, forKey: .customerID)
        try container.encode(type, forKey: .type)
        if type == "anniversary_date" 
            try container.encode(date, forKey: .anniversaryDate)
         else 
            try container.encode(date, forKey: .birthDate)
        
        try container.encode(customerName, forKey: .customerName)
        try container.encode(mobileNumber, forKey: .mobileNumber)
    

然后对数组进行编码并将Data对象写入UserDefaults

do 
    let jsonData = try JSONEncoder().encode(bestWishesArr)
    UserDefaults.standard.set(jsonData, forKey:"bestWishes")
 catch  print(error) 

【讨论】:

再次感谢@vadian。答案真的很有帮助!给了 。也赞成...:) 只是一个疑问..json中是否有isExist之类的方法来检查某个键是否存在...? 要么使属性可选,要么decodeIfPresent阅读有关 JSON 编码/解码的文档。这是值得的。 @v.bw 不要使用 UserDefaults 来存储您的应用数据。 UserDefaults 用于存储您的应用程序设置(即 UISwitch 状态)。只需将生成的 JSON 数据写入 App 支持目录中的 json 文件 顺便说一句,您还应该使用正确的 dateStrategyDecoding 选项将日期存储为 Date 并将手机号码存储为字符串。

以上是关于将 Decodable 结构存储到 Userdefaults的主要内容,如果未能解决你的问题,请参考以下文章

核心数据-[Decodable.Address initWithCoder:]:发送到实例的无法识别的选择器

Swift 4 Decodable - 将 JSON 对象解码为“数据”

使用 Swift 4 Decodable 将字符串 JSON 响应转换为布尔值

在 SwiftUI 中将 ObservableObject 链接到 DatePicker

当属性类型可能从 Int 更改为 String 时,如何使用 Decodable 协议解析 JSON?

有没有办法用 Decodable 忽略某些键,只提取它们的值?