Realm-cocoa: Class does not conform "Encodable" while using List<String> in swift 4.0

Created on 30 Oct 2017  路  7Comments  路  Source: realm/realm-cocoa

Goals

Using Codable and Realm in swift 4.0 with List\

Actual Results

Type 'News' does not conform to protocol 'Encodable'

Code Sample

class News: Object, Codable {
    var pictureList = List<String>()

    private enum CodingKeys: String, CodingKey {
        case  pictureList       
    }

    public required convenience init(from decoder: Decoder) throws {      
        self.init()

        let container = try decoder.container(keyedBy: CodingKeys.self)

        let pictures = try container.decodeIfPresent([String].self, forKey: .pictureList) ?? [""]
        pictureList = List(pictures)
    }
}

JSON is like

{
    "pictureList": [ 
        "String 1",
        "String 2",
        "String 3"
     ]
}

Version of Realm and Tooling

Realm framework version: 3.0.1

Xcode version: Version 9.0.1 (9A1004)

iOS/OSX version: iOS 10.0

Is it possible in this way? If not, is there any other way to meet my goal?

Thanks~

T-Help

Most helpful comment

@magic3584 Codable is defined as typealias Codable = Decodable & Encodable, so you should implement encode(to encoder: Encoder) method to conform Codable protocol. Or you can
conform Decodable if you do not need to encode Realm object to another format.

Also, assigning List property doesn't work. List properties should be declared let. So you can only append/remove objects to it/

class News: Object, Decodable {
    let pictureList = List<String>()

    private enum CodingKeys: String, CodingKey {
        case  pictureList
    }

    public required convenience init(from decoder: Decoder) throws {
        self.init()

        let container = try decoder.container(keyedBy: CodingKeys.self)

        let pictures = try container.decodeIfPresent([String].self, forKey: .pictureList) ?? [""]
        pictureList.append(objectsIn: pictures)
    }
}

All 7 comments

@magic3584 Codable is defined as typealias Codable = Decodable & Encodable, so you should implement encode(to encoder: Encoder) method to conform Codable protocol. Or you can
conform Decodable if you do not need to encode Realm object to another format.

Also, assigning List property doesn't work. List properties should be declared let. So you can only append/remove objects to it/

class News: Object, Decodable {
    let pictureList = List<String>()

    private enum CodingKeys: String, CodingKey {
        case  pictureList
    }

    public required convenience init(from decoder: Decoder) throws {
        self.init()

        let container = try decoder.container(keyedBy: CodingKeys.self)

        let pictures = try container.decodeIfPresent([String].self, forKey: .pictureList) ?? [""]
        pictureList.append(objectsIn: pictures)
    }
}

@kishikawakatsumi I added a compute [String] property with only get ,and a String property to save to Realm, but it's a little more ugly, your solution is perfect!
Thanks ~

Is it possible meet the goal without the func init(from decoder: ) throws because I have to write a few codes like property = try container.decodeIfPresent()

@magic3584 Currently, no. Compiler code generation support of Codable protocol works only a class has non-argument initializer (init()). Realm Object cannot be initialized by init().

@magic3584 No. You need to write mapping code in required convenience init(from decoder: Decoder) throws yourself. Compiler code generation doesn't work.

@kishikawakatsumi Got it, thanks~

Was this page helpful?
0 / 5 - 0 ratings