Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Codable while using Realm

Hy I am working on app that uses Realm and Alamofire. I am really happy in using these library in my iOS project.

But then I have to post a List of models that contains multiple lists of models. So that is too much deep thing I mean List inside List that contains models and those model contains list of several model

For demonstration lets just take an example of my models

@objcMembers public class MyModel : Object{
    dynamic var Id: String = ""
    dynamic var Name: String = ""
    dynamic var Favorites: List<String>? = nil 
    dynamic var Subjects: List<UserSubject>? = nil 
}


@objcMembers public class UserSubject: Object{
    dynamic var Id: String = ""
    dynamic var Name: String = ""
    dynamic var Teachers: List<Publications>? = nil 
}


@objcMembers public class Publications: Object{
    dynamic var Id: String = ""
    dynamic var Name: String = ""
    dynamic var Editors: List<Editors>? = nil 
}

So you can see these are models inside list that contains another list of model.

Due to Realm I am using List for list for creating the RelationShip.

Problem: but Now when I tries to implement Codable on Models/Struct It really unable to recognize List property.

I really do not know how to solve this problem? Do anyone have any Idea how to do it ?

UPDATE: I am using Swift 4.0 and base sdk is 11.2

like image 310
A.s.ALI Avatar asked Nov 16 '18 06:11

A.s.ALI


1 Answers

Had the same problem in a project and wrote these extensions:

import Foundation
import RealmSwift

extension RealmSwift.List: Decodable where Element: Decodable {
    public convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.singleValueContainer()
        let decodedElements = try container.decode([Element].self)
        self.append(objectsIn: decodedElements)
    }
}

extension RealmSwift.List: Encodable where Element: Encodable {
    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(self.map { $0 })
    }
}

With these extension you easily can make the Realm Object Codable. Like this

@objcMembers public class MyModel: Object, Codable {
    dynamic var id: String = ""
    dynamic var name: String = ""
    var favorites = List<String>()
    var subjects = List<UserSubject>()
}

@objcMembers public class UserSubject: Object, Codable {
    dynamic var id: String = ""
    dynamic var name: String = ""
    var teachers = List<Publications>()
}


@objcMembers public class Publications: Object, Codable {
    dynamic var id: String = ""
    dynamic var name: String = ""
    var editors = List<Editor>()
}

@objcMembers public class Editor: Object, Codable {

}
like image 149
Oliver Avatar answered Nov 15 '22 23:11

Oliver