Swift-将[String:Any]数组保存到NSUserDefauls

时间:2019-07-30 11:43:54

标签: ios swift nsuserdefaults codable decodable

我发现此扩展使用Codable保存到NSUserDefaults

NavigationLink

但是我发现我有一个错误extension UserDefaults { func decode<T : Codable>(for type : T.Type, using key : String) -> T? { let defaults = UserDefaults.standard guard let data = defaults.object(forKey: key) as? Data else {return nil} let decodedObject = try? PropertyListDecoder().decode(type, from: data) return decodedObject } func encode<T : Codable>(for type : T, using key : String) { let defaults = UserDefaults.standard let encodedData = try? PropertyListEncoder().encode(type) defaults.set(encodedData, forKey: key) defaults.synchronize() } } ,因为Type 'OfflineRequest' does not conform to protocol 'Decodable'

我要保存的下一个结构:

Any

该想法是持久存储由于任何连接问题而失败的请求的堆栈(数组)。因此,我具有Core Data数据模型,并且在将其属性发送到服务器之前将其属性转换为[String:Any]。但是现在我想创建离线优先算法。因此,如果用户处于脱机状态,我想持久存储url和params [String:Any]。在这种情况下如何正确处理struct OfflineRequest: Codable { let url: String let params: [String: Any] }

2 个答案:

答案 0 :(得分:2)

您可以使用... Repo : base/7/x86_64 ... 对字典进行编码,并使用JSONSerialization.data(withJSONObject: Any)对字典进行解码。您只需要确保传递有效的json对象(在本例中为字典)即可,如果传递的字典类型为JSONSerialization.JSONObject(with: Data),则它将崩溃。尝试这样:

Date

struct OfflineRequest: Codable {
    let url: String
    let params: [String: Any]
}

extension OfflineRequest {
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        url = try container.decode(String.self)
        params = try JSONSerialization.jsonObject(with: container.decode(Data.self)) as? [String:Any] ?? [:]
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(url)
        try container.encode(JSONSerialization.data(withJSONObject: params))
    }
}

答案 1 :(得分:0)

由于[String:Any]导致出现错误,建议您使用[String:Any]Data转换为JSONSerialization.data

然后您可以像这样使用

struct OfflineRequest: Codable {
    let url: String
    let params: Data


    enum CodingKeys: String, CodingKey {
        case url
        case params

    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        params = try values.decode(Data.self, forKey: .params)
        url = try values.decode(String.self, forKey: .url)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(url, forKey: .url)
        try container.encode(params, forKey: .params)
    }
}