I'm trying to learn Core Data, and am having trouble updating the MOC after adding new objects to an existing object. I can create the original object, a training day, and I can add exercise objects to that training day, but I can't figure out how to save the context so that later in my application I can find all exercises in a training day.
Any ideas??
Here is my code:
// Data from JSON
NSArray *trainingDayData = responseData[@"training_days"];
for (NSDictionary *aTrainingDay in trainingDayData) {
// Find the specific training day and save the MOC, creating the trainingDayObject
NSNumber *idTrainingDay = [NSNumber numberWithInt:[[aTrainingDay objectForKey:kID_KEY] intValue]];
VitTrainingDay *trainingDayObject = [VitTrainingDay trainingDayCreateOrObjectWithID:idTrainingDay];
// Configure the VitTrainingDay object's fields
trainingDayObject.name = aTrainingDay[@"name"];
trainingDayObject.order = aTrainingDay[@"order"];
}
// assign exercises to each trainingDayObject(this is inside a larger for loop)
trainingDayObject.userExercise = [NSSet setWithArray:userExerciseObjects];
// Below are attempt one and two to update the MOC after assigning exercises to the trainingDayObject.
// This works to save the updated MOC, but also adds two blank trainingDayObjects, since it 'insertNewObjectForEntityName', which I don't want.
trainingDayObject = [NSEntityDescription insertNewObjectForEntityForName:@"TrainingDay" inManagedObjectContext:self.context];
//This as far as I can tell is doing nothing. It just points to the conventional MOC save method. I pull it out below.
[self.coreDataManager saveContextForManagedObjectContext:self.context];
Here is the saveContextForManagedObjectContext
method I call above:
- (void)saveContextForManagedObjectContext:(NSManagedObjectContext *)moc
{
NSError *error = nil;
if (![moc save:&error]) {
NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}
}
I am a bit confused about your loops but assuming the first one is used to get each Training Day, sets some values and then get the Exercises for that day and set the relationships try the following.
Note that this line of code below is what creates the NSManagedObject, so you need to call it to create each TrainingDay object and each Exercise object.
trainingDayObject = [NSEntityDescription insertNewObjectForEntityForName:@"TrainingDay" inManagedObjectContext:self.context];
Not sure what this line does but presumably it creates a new object or returns one if it already exists
VitTrainingDay *trainingDayObject = [VitTrainingDay trainingDayCreateOrObjectWithID:idTrainingDay];
Unless it is also calling insertNewObjectForEntityForName
then it should be replaced with a call that does create the NSManagedObject or searches and returns one with a matching ID. If it is calling insertNewObjectForEntityForName
then you should remove the line below because that just creates another trainingDay
object in the database without setting any attribute values.
Try something like this
// Data from JSON
NSArray *trainingDayData = responseData[@"training_days"];
for (NSDictionary *aTrainingDay in trainingDayData) {
// Find the specific training day ID
NSNumber *idTrainingDay = [NSNumber numberWithInt:[[aTrainingDay objectForKey:kID_KEY] intValue]];
//Create the Core Data Object
//Assume VitTrainingDay is a NSManagedObject subclass
VitTrainingDay *trainingDayObject = [NSEntityDescription insertNewObjectForEntityForName:@"TrainingDay" inManagedObjectContext:self.context];
// Set the attributes
trainingDayObject.ID = idTrainingDay;
trainingDayObject.name = aTrainingDay[@"name"];
trainingDayObject.order = aTrainingDay[@"order"];
// assign exercises to each trainingDayObject
for (SomeSourceObject *object in SomeExercisesSource) {
ExerciseObject *exercise = [NSEntityDescription insertNewObjectForEntityForName:@"ExerciseObject" inManagedObjectContext:self.context];
// Set the exercises parent object (training day)
exercise.trainingDay = trainingDayObject;
exercise.details = object.details;
}
}
NSError *error = nil;
if (![self.context save:&error]) {
NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
} else {
NSLog(@"Save successful");
}
My guess is you need to search for an existing TrainingDay object with the same ID before creating a new one so if that is what this call [VitTrainingDay trainingDayCreateOrObjectWithID:idTrainingDay];
does then use it instead.