moyes
moyes

Reputation: 71

CoreData how to add items to a NSSet which is related to an entity

In my project I created two entities: Container and Items. There's a one to many relationship between the two. In Container I called the relationship item and I set it to "To Many" because I want to have many items in each container. In Items I called the relationship container and I set it to "To One" because each item must be associated to one and only one container.

This aside, in my project I have a tableview where I can add new containers and when I press on a cell I can see its items. The code to create the containers is fine. The problem comes when I try to create the items: they are created successfully but they appear in each container.

In the following part I'll post the objects, how I save containers and how I save items:

extension Container {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Container> {
        return NSFetchRequest<Container>(entityName: "Container")
    }

    @NSManaged public var name: String?
    @NSManaged public var index: Int64
    @NSManaged public var items: NSSet?

}

extension Items {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Items> {
        return NSFetchRequest<Items>(entityName: "Items")
    }

    @NSManaged public var text: String?
    @NSManaged public var image: UIImage?
    @NSManaged public var index: Int64
    @NSManaged public var container: Container?

}
let containerEntity = NSEntityDescription.entity(forEntityName: "Container", in: managedContext)!
        
        let items: NSSet = []
        
        let container = NSManagedObject(entity: containerEntity, insertInto: managedContext) as! Container
        
        ///Count is just an int variable
        container.setValue("Name", forKeyPath: "name")
        container.setValue(count, forKeyPath: "index")
        container.setValue(items, forKey: "items")
        
        do {
            try managedContext.save()

        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
        }
  let itemEntity = NSEntityDescription.entity(forEntityName: "Items", in: managedContext)!
        
        let items = NSManagedObject(entity: itemEntity, insertInto: managedContext) as! Items
 
        items.setValue("item", forKeyPath: "text")
        items.setValue(count, forKeyPath: "index")
     
        
        do {
            try managedContext.save()

        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
        }
        

Anyway I think that instead of creating items entities I should edit the container entity adding to it items. To do that I tried this but I feel like I'm missing something because this thing crashes.

let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "container")
       
       do {
           let test = try managedContext.fetch(fetchRequest)
           
           let objectUpdate = test[containerIndex] as! NSManagedObject
           
           objectUpdate.setValue("item", forKey: "text")
           objectUpdate.setValue(count, forKey: "index")
           
           do{
               try managedContext.save()
           } catch {
               print(error)
           }
          
       }
       catch {
           print(error)
       }

So how can I add items to a specific container?

Plus, is it ok if two of my entities attributes are called index?

Upvotes: 1

Views: 663

Answers (3)

song hwykyung
song hwykyung

Reputation: 11

Swift 5

If the relationship is properly set up in the Coredata-Model, The only thing you need to do is

item.container = container

    /*let container = NSManagedObject(entity: containerEntity, insertInto: managedContext) as! Container

    let items = NSManagedObject(entity: itemEntity, insertInto: managedContext) as! Items

    let containerEntity = NSEntityDescription.entity(forEntityName: "Container", in: managedContext)!

    let items = NSManagedObject(entity: itemEntity, insertInto: managedContext)*/

    //or

    let container = Container(context: managedContext)

    container.index = someIndex
    container.name = someName

    let item = Item(context: managedContext) // I think 'Item' would be better as a model name.

    item.text = someText
    item.image = someImage
    item.index = someIndex

    item.container = container // setting for Many to one relationShip

    do {
        try managedContext.save()

    } catch let error as NSError {
        print("Could not save. \(error), \(error.userInfo)")
    }

Upvotes: 0

Paulw11
Paulw11

Reputation: 115051

As long as you have set up the inverse relationships correctly in your core data model, the simplest approach is just to assign the relevant Container instance to the new Item's container property. Core data will take care of updating the Container's set of Items for you.

let itemEntity = NSEntityDescription.entity(forEntityName: "Items", in: managedContext)!
        
let items = NSManagedObject(entity: itemEntity, insertInto: managedContext) as! Items
 
items.setValue("item", forKeyPath: "text")
items.setValue(count, forKeyPath: "index")
items.setValue(container, forKeyPath: "container")

do {
    try managedContext.save()
} catch let error as NSError {
    print("Could not save. \(error), \(error.userInfo)")
}

Your code will be simpler and easier to maintain if you use the objects that are automatically created for your Core Data entities

        
let items = Item(context:managedObjectContext)
 
items.text = item
items.count = index
items.container = container

do {
    try managedContext.save()
} catch let error as NSError {
    print("Could not save. \(error), \(error.userInfo)")
}

Upvotes: 1

lorem ipsum
lorem ipsum

Reputation: 29676

If set up correctly a there should be an addToItems()

anyContainerObject.addToItems(value: Items)

Upvotes: 2

Related Questions