mikro098
mikro098

Reputation: 2343

Saving array of objects in Realm with Decodable

I've got a class which conforms to Decodable protocol (fetching data from API) and I would like to save it in the Realm database. Problem occurs when one of my properties is array (List). It says Cannot automatically synthesize Decodable because List<Item> does not conform to Decodable What is the best way to bypass this problem? Realm only supports arrays of primitive types.

here is my class:

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

Upvotes: 1

Views: 717

Answers (2)

Bibek
Bibek

Reputation: 3719

Dávid's solution didn't work for me completely. I had to tweak the solution instead by replacing decoder.unkeyedContainer() to decoder.singleValueContainer(), below is the solution.

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)
    }
}

Upvotes: 1

David Pasztor
David Pasztor

Reputation: 54716

Using the long awaited conditional conformances implemented in Swift 4.1, you can simply declare List to conform to Decodable in case its Element conforms to 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)
    }
}

To make this work for your specific case, you need to make sure that Item also conforms to Decodable.

If you also need Encodable conformance, simply extend List to support that as well.

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

Upvotes: 2

Related Questions