Irrational Exuberance!

Assigning One To Many Relationships in CoreData

February 24, 2008. Filed under objccoredatacocoa

Recently I have been using CoreData a bit, and have been really enjoying it. Combined with Cocoa Bindings it is a hell of an effective tool. But I did have a slightly frustrating time crawling examples and documentation to figure out managing relationships between entities. I did figure it out, but it was confusing enough (for someone new to Cocoa) to merit a more explicit example than found in the current documentation. Here is an example of adding a new instance of an entity in an one-to-many relationship with an existing entity.

There are two entities in use in the Core Data schema that this example is using: curriculum and lessonPlan. In reality they contain some additional information, but the relevent bit is that curriculum has a one-to-many relationship with lessonPlan. (The name of the app is StrictlyEducation, which I realize may not be shockingly original.)

Here is the entire StrictlyEducation_AppDelegate.h file.

#import <Cocoa/Cocoa.h>

@interface StrictlyEducation_AppDelegate : NSObject 
{
    IBOutlet NSWindow *window;
    IBOutlet NSArrayController *curriculums;
    IBOutlet NSArrayController *lessonPlans;   
    NSPersistentStoreCoordinator *persistentStoreCoordinator;
    NSManagedObjectModel *managedObjectModel;
    NSManagedObjectContext *managedObjectContext;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator;
- (NSManagedObjectModel *)managedObjectModel;
- (NSManagedObjectContext *)managedObjectContext;
- (IBAction)saveAction:sender;
- (IBAction)addLessonPlan:sender;
@end

And here is the implementation of the addLessonPlan:sender method, which is where I create new entries of lessonPlan, and associate them under the one-to-many lessonPlans relationship between one curriculum and many lessonPlans.

- (IBAction)addLessonPlan:(id)sender {
    NSManagedObjectContext *context = [self managedObjectContext];
    NSArray * selectedArray = [curriculums selectedObjects];
    NSManagedObject * selected = [selectedArray objectAtIndex:0];
    id lessonPlan = [NSEntityDescription insertNewObjectForEntityForName:@"LessonPlan" inManagedObjectContext:context];
    NSMutableSet * lessonPlansSet = [selected mutableSetValueForKey:@"lessonPlans"];
    [lessonPlansSet addObject:lessonPlan];
    [lessonPlanSet setValue:lessonPlansSet forKey:@"lessonPlans"];
    [context processPendingChanges];
}
  1. First you need to grab a hold of the NSManagedObjectContext, which it just so happens the AppDelegate is glad to help you with by using the managedObjectContext message.

  2. Next, you ask the primary NSArrayController which objects it has selected (using the selectedObjects message), and in this case the table is set to always have one and only one selection, so we know that we will be recieving one and only one object in the returned NSArray.

  3. Then we create a new instance of lessonPlan, using the rather long-winded insertNewObjectForEntityName:InManagedObjectContext: message.

  4. Fourth, we add this new lessonPlan to selected's (which is a curriculum) lessonPlans relationship.

  5. Finally, we tell the context to save the new changes, and release the now unnecessary lessonPlan and lessonPlansSet variables.

I wouldn't necessarily call it simple, but with an example to look at its certainly doable.


Other Cocoa CoreData Resources

  1. CocoaDevCentral has a great tutorial on building a Core Data application.
  2. CocoaDevCentral also has a good Core Data Class Overview.
  3. Apple has a decent, but at times frustratingly vague introduction to Core Data.
  4. But perhaps the best resource I've found is Apple's CoreRecipes example application.