【问题标题】:Swift - Encode and Decode a dictionary [String:Any] into plistSwift - 将字典 [String:Any] 编码和解码为 plist
【发布时间】:2019-05-04 06:43:53
【问题描述】:

我试图将字典存储在我的类 Marker 中,但它抛出一个错误,说它不可编码或不可解码。我可以看到错误是由 [String: Any] 引起的,但我该如何解决呢?

var buttonActions : [String: [String: [String:Any]]] = [:]

保存并加载

func saveData() {
    let dataFilePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("\(fileName).plist")

    let encoder = PropertyListEncoder()
    do {
        let data = try encoder.encode(markerArray)
        try data.write(to: dataFilePath!)
        print("Saved")
    } catch {
        print("Error Encoding \(error)")
    }
}

func loadData() {
    let dataFilePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("\(fileName).plist")

    if let data = try? Data(contentsOf: dataFilePath!){
        let decoder = PropertyListDecoder()
        do {
            markerArray = try decoder.decode([Marker].self, from: data)
        } catch {
            print("Decode Error \(error)")
        }
    }

class Marker : Encodable, Decodable {
    var UUIDpic: UUID = UUID()
    var alpha: Int = 1
    var buttonType: Int = 0
    var buttonActions : [String: [String: [String:Any]]] = [:]
    var buttonNameColor: String = ""
    var buttonNameFontSize: Int = 10
    var buttonShape: String = ""
    var loggerRect: String = ""
    var maskColor: String = ""
    var name: String = ""
}

【问题讨论】:

  • 您无法对Any 进行编码/解码。内部字典中实际包含哪些类型的值?
  • 内部字典包含一个字符串和一个字符串数组

标签: swift dictionary encoding nested decode


【解决方案1】:

很遗憾,您不能在包含Any 的泛型类型上使用encodedecode(例如[String: Any][Any])。 Any 不符合协议 Encodable 也不符合 Decodable 并且 Swift 不知道如何对其进行编码/解码。您必须为您的字典使用具体的泛型类型(例如[String: String])。

如果你仍然需要使用像Any 这样的通用类型,你必须实现encode(to:)init(from:) 方法。另一种选择是使用struct 而不是符合Codable (Encodable & Decodable) 的[String: [String: [String:Any]]]。您仍然需要在该结构中实现 encode(to:)init(from:) 方法,但好的一面是您不必为所有属性编写 encoder.encode() 故事,如果您在Marker 班级。

【讨论】:

  • 您好 Andrada,您可以提供链接或示例吗?我将我的类更改为结构,我有点理解你的意思,但我无法实现它抱歉。
  • 看看这个答案:stackoverflow.com/questions/44603248/… 同样,您不需要将您的类更改为结构,您需要为该字典添加一个额外的结构
  • 谢谢 Andrada,我现在就尝试实现它
  • 我浏览了链接,但我不明白如何实现最流行的答案,所以我使用了链接到该答案的 github。 gist.github.com/mbuchetics/5d5600c50c369bea29db4a3986cee94f 这种工作但如果我想在 [String:Any] 中添加一个数组则不行。有任何想法吗?谢谢
  • 感谢安德拉达的帮助。因为你,我设法解决了:)
【解决方案2】:

所以终于在 Andrada 的帮助下解决了。

我添加了第二个结构来保存动作,并且通过了必须使用 [string:any]

class Marker : Encodable, Decodable {
var UUIDpic: UUID = UUID()
var alpha: Int = 1
var buttonType: Int = 0
var buttonAction : [String: [ButtonAction]] = [:] //Dictionary I edited using the new struct
var buttonNameColor: String = ""
var buttonNameFontSize: Int = 10
var buttonShape: String = ""
var loggerRect: String = ""
var maskColor: String = ""
var name: String = ""
}

下面是我添加的结构

struct ButtonAction: Codable {
var action: String
var array_linked_of_buttons: [[String:String]]

init(action: String, array_linked_of_buttons: [[String:String]]) {
 self.action = action
 self.array_linked_of_buttons = array_linked_of_buttons
    }
}

确保初始化你的结构,否则它将无法工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    相关资源
    最近更新 更多