core-data 中具有自定义类型的所有属性都必须是关系吗?

Hon*_*ney 2 json core-data nsvaluetransformer swift codable

这是以下注释中的后续问题如何映射嵌套的复杂 JSON 对象并将它们保存到核心数据?

\n\n

想象一下我的应用程序已经有了这段代码。

\n\n
class Passenger{\n    var name: String\n    var number: String\n    var image : UIImage\n    // init method\n}\nclass Trip {\n    let tripNumber : Int\n    let passenger : Passenger\n\n    init(tripNumber: Int, passenger: Passenger) {\n        self.tripNumber = tripNumber\n        self.passenger = passenger\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我决定为我的应用程序添加持久性。我只想一张旅行表。我想向乘客显示行程,但不需要表格来直接查询乘客。它只是旅行的自定义对象/属性。每次我访问乘客都是通过 Trips。

\n\n

那么有没有一种方法可以让我创建一个名为 \'TripEntity\' 的新 NSManagedObject 子类并存储我的乘客 \xe2\x80\x94 ,而无需 1. 为 \'Passenger\' 创建另一个 NSManagedObject 子类 2. 创建与乘客和行程之间存在反比关系吗?简而言之,我只是希望它成为一个属性。从概念上讲,对我来说它也只是一个属性。这根本就不是一种关系……

\n\n

或者,一旦您使用 Core-data,那么每个自定义类型都需要显式成为 NSManagedObject 的子类?否则它不会被持久化。我猜这也是对象图的含义。你的图表需要完整。图表之外的任何内容都将被忽略......

\n\n

我问这个问题是因为我实际想要存储的 JSON 对象非常庞大,并且我正在尝试减少需要完成的工作。

\n

vad*_*ian 5

您可以将乘客添加到一个 Trip 实体,但由于属性类型受到限制,您必须使用一种transformable类型,该类型对于归档和取消归档对象可能非常昂贵。

\n\n

如果源数据是 JSON,最有效的方法是为Passenger和创建核心数据实体Trip并添加逆关系。然后让所有NSManagedObject类都采用Codable并为每个类添加init(from decoder方法encode(to encoder:

\n\n

例如,我们假设该类Trip与其具有一对多关系,Passenger如下所示

\n\n
@NSManaged public var tripNumber: Int32\n@NSManaged public var passengers: Set<Passenger>\n
Run Code Online (Sandbox Code Playgroud)\n\n

Passenger类中有一个属性trip

\n\n
@NSManaged public var trip: Trip?\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是Decodable中所需的初始值设定项Trip。解码器可以解码数组和集合。

\n\n
private enum CodingKeys: String, CodingKey { case tripNumber, passengers }\n\npublic required convenience init(from decoder: Decoder) throws {\n    guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Context Error") }\n    let entity = NSEntityDescription.entity(forEntityName: "Trip", in: context)!\n    self.init(entity: entity, insertInto: context)\n    let values = try decoder.container(keyedBy: CodingKeys.self)\n    tripNumber = try values.decode(Int32.self, forKey: .tripNumber)\n    passengers = try values.decode(Set<Passenger>.self, forKey: .passengers)\n    passengers.forEach{ $0.trip = self }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

反比关系通过线设置forEach
\n您必须添加 的扩展JSONDecoder才能传递对象NSManagedObjectContext中的电流userInfo

\n\n

相应的编码器是 \xe2\x80\x93 非常简单 \xe2\x80\x93

\n\n
public func encode(to encoder: Encoder) throws {\n    var container = encoder.container(keyedBy: CodingKeys.self)\n    try container.encode(tripNumber, forKey: .tripNumber)\n    try container.encode(passengers, forKey: .passengers)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

NSManagedObject采用的类Codable非常适合从 JSON 数据预填充数据库或进行 JSON 备份。

\n