使用Realm时如何实现Codable

时间:2018-11-16 06:44:32

标签: ios realm swift4 alamofire codable

为什么我正在开发使用Realm和Alamofire的应用程序。我真的很高兴在我的iOS项目中使用这些库。

但是随后我必须发布一个包含多个模型列表的模型列表。所以这太深了,我的意思是List里面的List包含模型,而那些模型包含几个模型的列表

为了演示,我们仅以我的模型为例

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

因此您可以看到列表中的这些模型包含另一个模型列表。

由于领域,我将List用于创建RelationShip的列表。

问题:,但是现在当我尝试在Models / Struct上实现Codable时,它真的无法识别List属性。

我真的不知道该如何解决这个问题?有人知道怎么做吗?

更新: 我正在使用Swift 4.0,基本sdk是11.2

4 个答案:

答案 0 :(得分:1)

您可以为列表使用扩展名

Swift 4.1

extension List: Decodable  where Element: Decodable {
    public convenience init(from decoder: Decoder) throws {
    // Initialize self here so we can get type(of: self).
    self.init()
    assertTypeIsDecodable(Element.self, in: type(of: self))
    let metaType = (Element.self as Decodable.Type) // swiftlint:disable:this force_cast

    var container = try decoder.unkeyedContainer()
    while !container.isAtEnd {
        let element = try metaType.init(__from: &container)
        self.append(element as! Element) // swiftlint:disable:this force_cast
    }
  }
}

extension List: Encodable where Element: Decodable {
    public func encode(to encoder: Encoder) throws {
       assertTypeIsEncodable(Element.self, in: type(of: self))
       var container = encoder.unkeyedContainer()
       for element in self {
           // superEncoder appends an empty element and wraps an Encoder around it.
           // This is normally appropriate for encoding super, but this is really what we want to do.
           let subencoder = container.superEncoder()
           try (element as! Encodable).encode(to: subencoder) // swiftlint:disable:this force_cast
       }
   }
}

答案 1 :(得分:1)

尝试一下:

extension List: Decodable where Element: Decodable {
    public convenience init(from decoder: Decoder) throws {
        self.init()
        var container = try decoder.unkeyedContainer()
        while !container.isAtEnd {
            let element = try container.decode(Element.self)
            self.append(element)
        }
    }
}

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

在这里找到它:How to use List type with Codable? (RealmSwift)

答案 2 :(得分:1)

我建议您使用Unrealm
它是一个功能强大的库,使您可以将Swift本机类型(结构,枚举,数组字典)保存到Realm数据库中。因此,您不必再担心列表和Codable兼容性。

enter image description here

An example model with Codable implementation

答案 3 :(得分:0)

在项目中遇到了相同的问题,并编写了以下扩展名:

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

有了这些扩展,您可以轻松地使Realm Object Codable成为可编码对象。像这样

@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 {

}