0
votes

I'm running into a CoreData problem related to one-to-many relationships.

Entity 1 - Authors has a one-to-many relationship with Entity 2 - Books. I think Books has a one-to-one relationship with Authors.

Since there are multiple books per author in the author object I have

@property (nonatomic, retain) NSSet *book;

The corresponding property in the book object is:

@property (nonatomic, retain) Authors *author;

When the app downloads books from the server through an API, after saving the book, I am trying to also save the author and associate the book with the author with the following code:

 NSEntityDescription *entity = [NSEntityDescription entityForName:@"Books" inManagedObjectContext:self.managedObjectContext];

 NSManagedObject *record = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
record setValue:bookname forKey:@"bookname"];

if ([self.managedObjectContext save:&error]) {
    Authors *newAuthor = [NSEntityDescription insertNewObjectForEntityForName:@"Authors" inManagedObjectContext:self.managedObjectContext];
                        newAuthor.aid = authorid;                      
                        newAuthor.book = record;
}

This code has worked for me for one to one relationships, but in this case, is throwing following exception error:

'NSInvalidArgumentException', reason: 'Unacceptable type of value for
 to-many relationship: property = "book"; desired type = NSSet; given 
 type = Books;

Can anyone suggest how to fix this?

Update:

I also tried switching it around to read:

record.author = newAuthor;

But this gives error

"property 'author' not found on object of type NSManagedObject"

although there is such a property defined in the Books object (as shown above).

2

2 Answers

0
votes

Since the book property is a set, CoreData should have created an Authors method such as addBookObject:. When you created your custom entity classes, there should be a file with a name similar to "Authors+CoreDataProperties.h". Look in there for defined methods.

Your second option should also work if you use Books instead of NSManagedObject. i.e.:

Books *record = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
0
votes

U can generate NSManagedObject subclass, after just create few objects, set relations and save context once, someting like:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:self.context];
Book *newBook = [[Book alloc] initWithEntity:entity insertIntoManagedObjectContext:self.context];
newBook.bookName = @"My new book";

NSEntityDescription *entity2 = [NSEntityDescription entityForName:@"Record" inManagedObjectContext:self.context];
Record *newRecord = [[Record alloc] initWithEntity:entity2 insertIntoManagedObjectContext:self.context];
newRecord.name = @"New record";

newBook.record = newRecord;
[newRecord addBook:[NSSet setWithObject:newBook]];

[self.context save:nil];

This is sample for db like below:

enter image description here

To autogenerate classes - select Entities in *.xcdatamodel file and press File->New->File select CoreData section and NSManaged Object subclass, go by wizard steps.

You will get something like

enter image description here

And even more:

enter image description here

Good tutorial u can also found here