You can add passengers to one Trip entity but as the attribute types are restricted you have to use a transformable
type which can be quite expensive to archive and unarchive the objects.
The most efficient way if the source data is JSON is to create Core Data entities for Passenger
and Trip
and add inverse relationships. Then make all NSManagedObject
classes adopt Codable
and add init(from decoder
and encode(to encoder:
methods to each class.
For example let's assume that the Trip
class has a to-many relationship to Passenger
it could look like
@NSManaged public var tripNumber: Int32
@NSManaged public var passengers: Set<Passenger>
and in the Passenger
class there is an attribute trip
@NSManaged public var trip: Trip?
this is the required Decodable
initializer in Trip
. The decoder can decode arrays as well as sets.
private enum CodingKeys: String, CodingKey { case tripNumber, passengers }
public required convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Context Error") }
let entity = NSEntityDescription.entity(forEntityName: "Trip", in: context)!
self.init(entity: entity, insertInto: context)
let values = try decoder.container(keyedBy: CodingKeys.self)
tripNumber = try values.decode(Int32.self, forKey: .tripNumber)
passengers = try values.decode(Set<Passenger>.self, forKey: .passengers)
passengers.forEach{ $0.trip = self }
}
The inverse relationship is set via the forEach
line.
You have to add an extension of JSONDecoder
to be able to pass the current NSManagedObjectContext
in the userInfo
object.
The corresponding encoder is – pretty straightforward –
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(tripNumber, forKey: .tripNumber)
try container.encode(passengers, forKey: .passengers)
}
NSManagedObject
classes adopting Codable
are very comfortable for pre-populating the database from JSON data or making JSON backups.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…