如何使用Codable的List类型?(RealmSwift)

Yos*_*iri 6 realm swift swift4

问题是List类型不符合Codable,下面的类不能插入Realm.

例如,

class Book: Codable {
    var name: String = ""
    var author: String = ""
    var tags = [String]()
}
Run Code Online (Sandbox Code Playgroud)

考虑上面的类符合Codable,如果将此类存储到Realm,则需要使用List<Object>类型而不是[String]

class Book: Object, Codable {
    @objc dynamic var name: String = ""
    @objc dynamic var author: String = ""
    var tags = List<Tag>()

    required convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        author = try container.decode(String.self, forKey: .author)
        tags = try container.decode(List<Tag>.self, forKey: .tags)   // this is problem.
    }
}

class Tag: Object, Codable {
    @objc dynamic var string: String = ""

    required convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        string = try container.decode(String.self, forKey: .string)
    }
}
Run Code Online (Sandbox Code Playgroud)

为了符合Codable,它应该是实现Decodable协议.(required convenience init(from decoder: Decoder) throws)

但是,List类型不符合Codable(Decodable),如果类具有List类型,则不可能使用Codable .

如何解决这个问题?

谢谢,

Ans*_*Yao 11

我们可以使用扩展来使List符合Codable:

extension List : Decodable where Element : Decodable {
    public convenience init(from decoder: Decoder) throws {
        self.init()
        var container = try decoder.unkeyedContainer()
        while !container.isAtEnd {
            let element = try container.decode(Element.self)
            self.append(element)
        }
    } }

extension List : Encodable where Element : Encodable {
    public func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        for element in self {
            try element.encode(to: container.superEncoder())
        }
    } }
Run Code Online (Sandbox Code Playgroud)

如果其他人需要,我还获得了RealmOptional的扩展.

https://gist.github.com/ansonyao/41137bb3cbbca8ef31a13b6bc96ee422


Gui*_*rez 6

你快到了.在初始化程序内,您可以使用解码的数组初始化列表.基本上,改变

tags = try container.decode(List<Tag>.self, forKey: .tags)   // this is problem.
Run Code Online (Sandbox Code Playgroud)

let tagsArray = try container.decode([Tag].self, forKey: .tags)   
tags = List(tagsArray) // Now you are good
Run Code Online (Sandbox Code Playgroud)

正如评论中指出的那样,List构造函数不再像这样工作

你现在想要:

tags.append(objectsIn: tagsArray)
Run Code Online (Sandbox Code Playgroud)