How to set a reference from one object to another?
SOLVED
I misspelled the property department -> Department. Thanks for the answers and a big SORRY
Hi,
Imagine the obvious model of employees and departments, where each employee must refer to a single department, and each department may have none to many employees.
For Employee I have a pointer to Department, and I set its value to the address of the object of the relevant Department.
For Department I have a NSSet, to which I can add employees.
The problem is that when I create a new employee and a new department, the objects exist in the memory at some place. The reference from Employee to Department, and vice versa, contains these addresses. When I'll fetch the data it will be located at a different location. So it is not clear how the connection between these objects is done.
Here is the code as I understand it should be:
// Fetch Plist object
NSDictionary *plistDictionary = [[NSDictionary alloc] initWithDictionary:plistData];
// Create Department Entity
Department *department = (Department *)[NSEntityDescription
insertNewObjectForEntityForName:@"Department"
inManagedObjectContext:managedObjectContext];
// Set properties
[department setName:[plistDictionary valueForKey:@"department"]];
// Create Employee entity
Employee *employee = (Employee *)[NSEntityDescription
insertNewObjectForEntityForName:@"Employee"
inManagedObjectContext:managedObjectContext];
// Set properties
[employee setFileName:[plistDictionary valueForKey:@"picture"]];
[employee setName:[plistDictionary valueForKey:@"name"]];
// Set relationship
[employee setDepartment:department];
[department addEmployee:employee];
// Save data to core data
[self saveAction];
And here is the Error I get:
2010-04-08 16:06:11.295 Paparazzi2[2656:207] ERROR:saveAction. Unresolved Core Data Save error Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x3d1c6f0 "Operation could not be completed. (Cocoa error 1570.)", {
NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1570.)";
NSValidationErrorKey = department;
NSValidationErrorObject = <Employee: 0x3d13a30> (entity: Employee; id: 0x3d16670 <x-coredata:///Employee/t8C950118-C388-4020-8CD9-1F49138A94193> ; data: {
picture = "mike.jpg";
name = "Mike Smith";
department = nil;
}); }
Thanks, Tzur.
Hey Tzur, one problem with the code you provide is that you're trying to assign the department relationship a value that is not a managed object.
You should first create the Department
object if it doesn't already exist, and use that object as the value of the department relationship.
I would replace this line:
[employee setDepartment:[object valueForKey:@"department"]];
With this:
Department *myDepartment = [self fetchDepartmentNamed:[object objectForKey:@"department"]
inManagedObjectContext:[self managedObjectContext]];
if (!myDepartment) {
/* no existing department with that name.. create one */
myDepartment = (Department *)[NSEntityDescription insertNewObjectForEntityForName:@"Department" inManagedObjectContext:[self managedObjectContext]];
[myDepartment setName:[object objectForKey:@"department"]];
}
/* assign the relationship to the department managed object */
[employee setDepartment:myDepartment];
This assumes you have defined a method -(Department *)fetchDepartmentNamed:inManagedObjectContext:]
that will build a fetch request and get a Department with the name you provide (also assumes your department names are unique)
Alternatively, you could just add the employee to myDepartment's "employees" relationship, and it would achieve the same result.
Ok, so you have updated your code, and now you have this:
// Set relationship
[employee setDepartment:department];
[department addEmployee:employee];
You should have done, one or the other... not both. Check in the managed object model that you have selected the "Inverse:" of the relationship for both entities. If you set one of the relationships, Core Data will manage the reverse (inverse) of the relationship.
You can't use nil in an NSDictionary. If you haven't synthesized classes to represent your managed objects, you have to use the NSNull
class. So, assuming employee
is an instance of NSManagedObject
and represents your Employee
entity:
[employee setValue:[NSNull null] forKey:@"department"];
This is used to sever whatever relationship this instance of Employee
had with its previous department. If you do set this to nil, however, the department
attribute must be optional or you will have a validation error when you try to save your object graph (context).
精彩评论