UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

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.