1110
1110

Reputation: 6829

How to add nested object to exising object in core data

I have one to many objects Driver <-->> Car.
Classes:

class Driver: NSManagedObject {
   @NSManaged var fullName: String
    @NSManaged var cars: NSSet
}
class Car: NSManagedObject {
   @NSManaged var model: String
   @NSManaged var year: String
   @NSManaged var driver: Driver
}

I inserted one Driver and a few car objects.
But I don't know what is the proper way to update car list to add or remove some car object.
Wired but I can't find any example on net how to do this.
So how to just add new car to existing driver or remove car from it?

UPDATE I tried something like this but it saves new car in database but those new cars are not related to driver.
When I fetch driver in cars:NSSet I am still getting one car.

let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext;

        var newCar:Car = NSEntityDescription.insertNewObjectForEntityForName("Car", inManagedObjectContext: context!) as! Car

        newCar.year = "1977";

        var cars = driver?.cars.allObjects as! [Car]

        cars.append(newCar)

        var err: NSError?;

        context?.save(&err);

Upvotes: 0

Views: 2764

Answers (3)

danu
danu

Reputation: 1178

Based on @Gil Sand's answer let me write what worked for me in swift when it comes to saving nested objects to coredata.

  1. Create your NSManagedObject instance of the parent object entity which u wants to saved in to.

2.Create new instances of your sub-objects

  1. Add the instances in to your containing object as key value pairs and save the context

    for car in cars { 
     //Step 1
       let entity = NSEntityDescription.insertNewObject(forEntityName: "Car", into: managedObjectContext)
    
     // Step 2
       let driver_entity =  NSEntityDescription.entity(forEntityName: "Driver", in: managedObjectContext)
    
        let driver = Driver(entity: driver_entity, insertInto: managedObjectContext)
    
       driver.name = "Sean Paul"
       driver.age = "46"
    
     //Step 3
     entity.setValue(model, forKey: "model")
     entity.setValue(year, forKey: "year")
     entity.setValue(driver, forKey: "driver") // the key name "driver" is the entity relationship name you define in your coredata model
    
     managedObjectContext.insert(entity)
     }
    
    
          do {
                try managedObjectContext.save()
          } catch {
                print("Failed saving car details")
          }
    

Upvotes: 0

Gil Sand
Gil Sand

Reputation: 6040

EDIT: I just realized you asked for swift, which I don't know. My answer isn't really valid then but let's just hope you can read through it :) The logic is the same anyways so I won't delete it.

I'll quote Mundi's answer by saying that you should use the autogenerated files once you've built your model using the core data model. It's incredibly easy and effective. And fast.

To add a sub-object to your object, you simply need to

  1. Fetch or Create your object
  2. Create new instances of your sub-objects
  3. Add those instances to your "containing" object.
  4. Save the managedObjectContext

    //A method that returns your object 
    -(Car*)getCarById:(NSString*)carId inContext:(NSManagedObjectContext*)context{
        NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Cars" inManagedObjectContext:context];
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        [request setEntity:entityDescription];
    
        //NSPredicate has to be used to fetch the correct car. I'll assume you know that.
    
        NSError *error;
        NSArray *array = [context executeFetchRequest:request error:&error];
        if (array.count > 0)
            return (array.firstObject);
    }
    

If this methods doesn't return your Car/Driver, create it.

Car *car = [self getCarById:myId inManagedObjectContext:context];
    if(!car)
    {
        car = [NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:context];
    }

You now HAVE your object(s), and all of it's sub objects if there are any (even with a fault status).

now if I have a Driver object (that I got using the same methods), I can simply use

[car addDriver:driver];

because this method was autogenerated when i created my model.

if you have your driver by himself, you can go upwards and give him another car

driver.car = car;

I haven't really tested when doing it in that direction but I think you should be fine, core data is pretty powerful when it comes to simple stuff like that.

Also this is all very blurry to me, addDriver: might be addObject or setDriver, maybe insertDriver. I don't fully remember but you should be able to find them in the .h files anyway. :)

Upvotes: 1

Mundi
Mundi

Reputation: 80265

First, variabel names in Core Data, by convention start with lower case letters. Thus, fullName, not FullName.

Second, you do not write this file yourself. Instead, you use the model editor and have Xcode generate the class files.

In the model editor, establish a to-many relationship cars, from the Driver entity that points to the Car entity. Establish a reverse to-one relationship driver from Car to Driver.

Now you can add a car to a driver like

ferrari.driver = niki

Upvotes: 1

Related Questions