Как реализовать Codable при использовании Realm - PullRequest
0 голосов
/ 16 ноября 2018

Hy Я работаю над приложением, которое использует Realm и Alamofire.Я действительно счастлив использовать эту библиотеку в своем проекте iOS.

Но тогда я должен опубликовать Список моделей, который содержит несколько списков моделей.Так что это слишком глубоко, я имею в виду Список внутри Списка, который содержит модели, а эти модели содержат список из нескольких моделей

. Для демонстрации давайте просто возьмем пример моих моделей

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

Итак, выможно увидеть, что это модели внутри списка, который содержит другой список моделей.

Из-за Королевства я использую Список для списка для создания RelationShip.

Проблема: , но теперь, когда я пытаюсь реализовать Codable для моделей / структур, он действительно не может распознать свойство List.

Я правда не знаю, как решить эту проблему?У кого-нибудь есть идеи как это сделать?

ОБНОВЛЕНИЕ: Я использую Swift 4.0 и базовый sdk составляет 11,2

Ответы [ 3 ]

0 голосов
/ 22 ноября 2018

Попробуйте это:

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

Нашел здесь: Как использовать Тип списка с Codable? (RealmSwift)

0 голосов
/ 23 ноября 2018

У меня была та же проблема в проекте, и они написали следующие расширения:

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

}
0 голосов
/ 17 ноября 2018

Вы можете использовать расширения для списка

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