NEW: Subscribe to Hacking with Swift+ and accelerate your learning! >>

SOLVED: Codable in Core Data with to many relationships

Forums > Swift

I've been able to find multiple articles about codable in core data and decoding JSON. But I'm struggling when a to-many relationship exists. I currently have the following which works, but how do I filter the JSON based on an attribute in the child?

Checklist entity (Checklist <--->> TestGroup, relationship called hasTestGroups)

required convenience public init(from decoder: Decoder) throws {
    guard let contextUserInfoKey = CodingUserInfoKey.context,
      let managedObjectContext = decoder.userInfo[contextUserInfoKey] as? NSManagedObjectContext,
      let entity = NSEntityDescription.entity(forEntityName: "Checklist", in: managedObjectContext) else {fatalError("Failed to decode Checklist")}

    self.init(entity: entity, insertInto: managedObjectContext)
    let values = try decoder.container(keyedBy: CodingKeys.self)
    do {
      name = try values.decode(String?.self, forKey: .name)
      hasTestGroups = NSSet(array: try values.decode([TestGroup].self, forKey: .hasTestGroups))
    } catch {
      print("decoding error")
    }
  }

Then in a view where I decode the JSON:

guard let url = Bundle.main.url(forResource: "masterdatabase", withExtension: "json") else {fatalError("no file")}
                do {
                  let json = try Data(contentsOf: url)
                  let decoder = JSONDecoder()
                  decoder.userInfo[CodingUserInfoKey.context!] = self.moc
                  do {
                    let subjects = try decoder.decode([Checklist].self, from: json)
                    subjects.first?.name = self.desiredChecklistName
                    subjects.first?.eventNumber = Int32(self.desiredChecklistNumber)!
                    subjects.first?.eventDate = self.desiredChecklistData

How do I filter the JSON on decode based on something like TestGroup.name? It's a NSSet, so .filter{$0...} doesn't work.

   

How does the model class look like? Even though Xcode generates relationships as NSSet you can easily change that to Set and it will work just fine.

   

Adding to the previous reply... You cant use NSSet like an array. What you can do though is to access the NSSet as an array by doing the following -

Go to your xcdatamodel and select the entity. Go to the attribute panel of the entity and change the Codgen attribute from Class definition to Manual/None Select Editor then Create NSManagedOject Subclass - Click Next, then make sure your entity is selected then click next. Make sure the yellow folder for your project is selected from the Group drop down then click Create. This will create the NSManaged Object files for your entity. Select the file which contains properties (attributes) for your entity and there you will see your attributes and relationships you have set for your entity. Below them add the following code -

public var nameArray: [PutTheNameOfTheEntityWhichThisEntityIsrRelatedToHere] {
        let set = nameOfTheNSSetInThisEntity as? Set<PutTheNameOfTheEntityWhichThisEntityIsrRelatedToHere> ?? []

        return set.sorted {
            // Put the sorting method you want here
            // For example if the entity has an attribute called title then you would put this
            $0.title < $1.title
            // This will sort the array based on its title 
        }
    }

Once you do this you can access this array in code EntityName.nameArray. Hope this helps

   

Sorry, just realised that this will not work when you want your entity to conform to Codable. There has been a couple of forum posts about this and we have not been able to find a way to get NSSet to conform to Codable. Im atill hunting for a way but have been unabke to find it.

   

Thanks everyone! Worked like a charm!

   

Hacking with Swift is sponsored by Paw

SPONSORED Use Paw to build, test and describe web APIs. Paw has a lightning fast native macOS interface to compose requests, collaborate in real-time on API specs, and generate client code for your applications. You can import and export API definitions.

Discover Paw for Mac

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

Not logged in

Log in
 

Link copied to your pasteboard.