I’m using custom classes for my CoreData stack. Class properties are set properly in the model. There’s some points in the app that are abstracted to use setValue… on an NSManagedObject, but I have a few cases where that fails with an NSInvalidArgumentException, specifically when setting a related object; error indicates it wants the specific type, and it’s’ getting an NSManagedObject, hence the error. So, I thought I would just take the short route and cast my instance prior to the offending call, if it’s of a certain entity; like this:
NSManagedObject *addressObject = [NSEntityDescription insertNewObjectForEntityForName:@"Address" inManagedObjectContext:[object managedObjectContext]];
if ([[[object entity]name] isEqualToString:@"Hospital"]) {
Contact *contact = (Contact*)object;
DLog(@"The class of contact is: %@", [contact class]);
contact.Address = addressObject;
}
else{
[object setValue:addressObject forKey:@"Address"];
}
I know, Address shouldn’t be capitalized; I inherited this mess… anyway, I would totally expect that the contact object is a Contact, but it’s not, it’s an NSManagedObject! What am I doing wrong with the cast? Everything I’ve uncovered says this is the right way to cast, but for some reason, it’s not working for me here. Of course, this wouldn’t be necessary if the addressObject didn’t complain about getting an NSManagedObject instead of a Contact (sorry, Hospital inherits from Contact here), and that’s another baffling thing, but first things first. How can I coerce object to type Contact, which it really is?
Here’s the relevant trace:
* Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Unacceptable type of value for to-one relationship: property = “Contact”; desired type = Contact; given type = NSManagedObject; value = …
For completeness sake, the Address class has declaration for Contact as:
@property (nonatomic, retain) NSManagedObject * Contact;
with implementation for Contact as the normal dynamic, like:
@dynamic Contact;
Maybe I need some sleep? 😉 Thanks
The cast isn’t your problem. Casting doesn’t change what class an object is — just what the compiler thinks it is.
You object is an NSManagedObject but not a
Contactinstance. In you code theobjectyou have is aHospitalentity. Double-check that theHospitalentity is set to use theContactclass (or a subclass)).It is important to note that Entity inheritance and Objective-C class inheritance don’t have to match. I.e. you can have
Hospitalbe a subentry ofContactand still have theContactentity map to aContactclass withoutHospitalmap to a subclass of theContactclass. It is valid for theHospitalentity to map to the (same)Contactclass or even toNSManagedObject(which is what I suspect you’ve done).This may seem confusing but can be very powerful if used correctly.