LAST CHANCE: Save 50% on all my Swift books and bundles! >>

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.

2      

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.

2      

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

2      

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.

2      

Thanks everyone! Worked like a charm!

2      

Hacking with Swift is sponsored by Essential Developer.

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until July 28th.

Click to save your free spot now

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.