如何将 List 类型与 Codable 一起使用? (领域斯威夫特)

How to use List type with Codable? (RealmSwift)

问题是List类型不符合Codable,以下class无法插入到Realm中。

例如,

class Book: Codable {
    var name: String = ""
    var author: String = ""
    var tags = [String]()
}

考虑到上面的class符合Codable,如果把这个class存到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)
    }
}

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

但是,List类型不符合Codable(Decodable),如果class有List类型,则无法使用Codable .

如何解决这个问题?

谢谢,

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

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

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

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

你现在想要:

tags.append(objectsIn: tagsArray)

接受的答案只有一个问题。 Realm 指定列表应该是 let(Constants) 因此,要修改解决方案以遵循最佳实践,您只需将列表设为 let,然后循环将结果附加到数组。

// Change this Line in [Your Code]
// to a let (Constant)

var tags = List<Tag>()let tags = List<Tag>()

然后改变

tags = try container.decode(List<Tag>.self, forKey: .tags)

let tagsArray = try container.decode([Tag].self, forKey: .tags)   
tagsArray.forEach{ tags.append([=12=]) }

这就是您创建领域的方式/Swift 4 个可编码模型。

有关 JSON 响应、模型和 URLSession 的更多详细信息:Read this article

import RealmSwift

class VendorsList : Object, Decodable {
    @objc dynamic var id : Int = 0
    @objc dynamic var name : String?
    @objc dynamic var logo : String?
    // Create your Realm List.
    var kitchensList = List<VendorKitchens>()

    override class func primaryKey() -> String? {
        return "id"
    }

    private enum CodingKeys: String, CodingKey {
        case id
        case name
        case logo
        // Set JSON Object Key
        case kitchensList = "kitchens"

    }

    public required convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(Int.self, forKey: .id)
        self.name = try container.decode(String.self, forKey: .name)
        self.logo = try container.decode(String.self, forKey: .logo)
        // Map your JSON Array response
        let kitchens = try container.decodeIfPresent([VendorKitchens].self, forKey: .kitchensList) ?? [VendorKitchens()]
        kitchensList.append(objectsIn: kitchens)

    }

}


class VendorKitchens : Object, Decodable {
    @objc dynamic var id : Int = 0
    @objc dynamic var name : String?

    override class func primaryKey() -> String? {
        return "id"
    }

    private enum CodingKeys: String, CodingKey {
        case id
        case name
    }
}

我们可以使用扩展来使 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())
        }
    } }

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

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