Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

CoreData - Load Related Entities?

I'm just getting started tryuing my hand at CoreData and am wondering how to populate related entities. The Pun series showed how to load CoreData into a single entity (Pun), but I have entities contained within other entities, in my example Books have Authors. I have an array of NSStrings in a Dictionary object that I would like to 'stuff' into NSManagedObject *authors, which is an entity with firstName, lastName in it. How does this work? :)

Thanks! ~Mike

1 Answer

Amit Bijlani
STAFF
Amit Bijlani
Treehouse Guest Teacher

There are few things you would have to do:

  1. Create a data model for Author and Book.
  2. Create a one-to-many relationship between Author and Book.
  3. Create an NSManagedObject subclass for Author and Book. In your Book class you can create a property of class Author.

For example:

@interface Author : NSManagedObject
    @property (nonatomic, strong) NSString *firstName;
    @property (nonatomic, strong) NSString *lastName;
    @property (nonatomic, strong) NSString *bio;
@end

@interface Book : NSManagedObject
    @property (nonatomic, strong) NSString *title;
    @property (nonatomic, strong) NSString *description;
    @property (nonatomic, strong) Author *author;
@end

When you fetch a book it will also retrieve the author. When you save a book you will have to save the author along with it. Hope that makes sense. For more on relationships look for Core Data Programming: Relationships and Fetched properties in the help section.

Thanks, Amit! My issue was with the way to connect the related objects. I think I solved it using the following (or is there a better way of doing it?):

self.sourceTitle = [[dictionary objectForKey: @"volumeInfo"] valueForKey: @"title"];
NSArray *authorsArray = [[dictionary objectForKey: @"volumeInfo"] objectForKey:@"authors"];
for (NSString *newAuthor in authorsArray)
{
    Author *author = [NSEntityDescription insertNewObjectForEntityForName:@"Authors" inManagedObjectContext: self.managedObjectContext];
    author.name = newAuthor;
    [self.authors addObject:author];
}
self.sourceDescription = [[dictionary objectForKey: @"volumeInfo"] valueForKey: @"description"];
self.publisher = [[dictionary objectForKey: @"volumeInfo"] valueForKey: @"publisher"];
self.publishedDate = [[dictionary objectForKey: @"volumeInfo"] valueForKey: @"publishedDate"];
self.pageCount = [[dictionary objectForKey: @"volumeInfo"] valueForKey: @"pageCount"];

It's just that this method of creating new Author objects and attaching them one by one seems so kludgy compared to how smooth and elegant other CoreData processes work.

This looks pretty good. Adding them 1-by-1 isn't really an issue because nothing is committed to the database until you call -[NSManagedObjectContent save:]. You could add them as a batch by calling -setAuthors: but then you'd still need a temporary array to hold the objects. Another way you could do it is by doing author.book = self.

I hope this helps!

That's very interesting! if I did authors.book = self; would the changes to to either authors or book make it to the MOC, or would the changes be lost? I imagine the changes don't carry over after the addObject method is called?

Any changes you made will be saved when you call -[NSManagedObjectContent save:]

I guess to get more to the point I was trying to get at: assigning book as a property the the author object will pass the book by reference (and vice-versa) rather than by value (which wouldn't recognize any changes I would make after creating the relationship and before saving)?

Ah yes, that is correct!

Excellent, hope I'm not being too picky, but this is really helping! :) So then is the addObject method by-reference as well?

Amit Bijlani
Amit Bijlani
Treehouse Guest Teacher

Objects are all passed by reference. That's why when declaring them, you put an asterisk before the variable name implying that you are pointing to a value. When you pass it around you are passing the pointer and never the value.