Сохранение массива объектов в Realm с помощью Decodable

У меня есть класс, который соответствует протоколу Decodable (выборка данных из API), и я хотел бы сохранить его в базе данных Realm. Проблема возникает, когда одним из моих свойств является массив (список). Это говорит Cannot automatically synthesize Decodable because List<Item> does not conform to DecodableКаков наилучший способ обойти эту проблему? Realm поддерживает только массивы примитивных типов.

вот мой класс:

class PartValue: Object, Decodable {
    @objc dynamic var idetifier: Int = 0
    let items = List<Item>()
}

1 ответ

Решение

Используя долгожданные условные соответствия, реализованные в Swift 4.1, вы можете просто объявить List соответствовать Decodable если его Element соответствует Decodable,

extension List: Decodable where List.Element: Decodable {
    public convenience init(from decoder: Decoder) throws {
        self.init()
        var container = try decoder.unkeyedContainer()
        let array = try container.decode(Array<Element>.self)
        self.append(objectsIn: array)
    }
}

Чтобы это работало для вашего конкретного случая, вы должны убедиться, что Item также соответствует Decodable,

Если вам также нужно Encodable соответствие, просто расширить List чтобы поддержать это также.

extension List: Encodable where List.Element: Encodable {
    public func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(contentsOf: Array(self))
    }
}

Решение Давида не сработало для меня полностью. Я должен был настроить решение вместо того, чтобы заменить decoder.unkeyedContainer() в decoder.singleValueContainer()ниже решение.

extension List: Decodable where List.Element: Decodable {
    public convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.singleValueContainer()
        let array = try container.decode([Element].self)
        self.append(objectsIn: array)
    }
}
Другие вопросы по тегам