使用相同的类/模型进行网络和本地api

时间:2017-12-13 01:52:39

标签: swift realm swift4

当我创建网络请求时,我使用新的Swift 4

let user = try JSONDecoder().decode(UserCodable.self, from: data)

这将我的api模型变成了一个我可以使用的快速模型。这非常有效:

struct User: Codable {
    let id: Int
    let username: String
    let email: String
}

这非常适合网络,但我开始使用realm来创建本地数据库。对于数据库中的每个表,我必须创建一个类模型,因此如果我想创建一个Users表,我必须创建一个包含以下字段的域类:idusername和{{1} }。那么这是否意味着我将要用于管理用户的类?我觉得有不同的做事方式

1 个答案:

答案 0 :(得分:1)

Realm模型类可以符合Codable,因此不需要两种不同的类型。

您只需要将User转换为某个类,让它继承自Object,让Realm知道它是一个Realm模型类并标记所有属性@objc dynamic使它们成为托管属性。

class User: Object, Codable {
    @objc dynamic var id:Int = 0
    @objc dynamic var username:String = ""
    @objc dynamic var email:String = ""
}

List不符合Decodable开箱即用,所以要创建一个类Decodable即使它有多对多的关系,你也需要实现一个自定义init(from decoder:)方法。

let userJSON = """
{
    "id":1,
    "username":"John",
    "email":"example@ex.com",
    "dogs":[
        {"id":2,"name":"King"},
        {"id":3,"name":"Kong"}
    ]
}
"""

class Dog: Object,Codable {
    @objc dynamic var id:Int = 0
    @objc dynamic var name:String = ""
}

class User: Object, Decodable {
    @objc dynamic var id:Int = 0
    @objc dynamic var username:String = ""
    @objc dynamic var email:String = ""
    let dogs = List<Dog>()

    private enum CodingKeys: String, CodingKey {
        case id, username, email, dogs
    }

    required convenience init(from decoder: Decoder) throws {
        self.init()
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        username = try container.decode(String.self, forKey: .username)
        email = try container.decode(String.self, forKey: .email)
        let dogsArray = try container.decode([Dog].self, forKey: .dogs)
        dogs.append(objectsIn: dogsArray)
    }
}

let decodedUser = try? JSONDecoder().decode(User.self, from: userJSON.data(using: .utf8)!)