CJ.
CJ.

Reputation: 1044

Adding custom methods to a subclassed NSManagedObject

I have a Core Data model where I have an entity A, which is an abstract. Entities B, C, and D inherit from entity A. There are several properties defined in entity A which are used by B, C, and D.

I would like to leverage this inheritance in my model code. In addition to properties, I am wondering if I can add methods to entity A, which are implemented in it's sub-entities.

For example:

  1. I add a method to the interface for entity A which returns a value and takes one argument
  2. I add implementations of this method to A, B, C, D
  3. Then, I call executeFetchRequest: to retrieve all instances of B
  4. I call the method on the objects retrieved, which should call the implementation of the method contained in B's implementation

I have tried this, but when calling the method, I receive:

[NSManagedObject methodName:]: unrecognized selector sent to instance

I presume this is because the objects returned by executeFetchRequest: are proxy objects of some sort.

Is there any way to leverage inheritance using subclassed NSManagedObjects?

I would really like to be able to do this, otherwise my model code would be responsible for determining what type of NSManagedObject it's dealing with and perform special logic according to the type, which is undesirable.

Any help is appreciated, thanks in advance.

Upvotes: 15

Views: 8661

Answers (4)

Yuji
Yuji

Reputation: 34185

It should work. The objects returned by executeFetchRequest: are real instances of NSManagedObjects (or subclasses thereof.) The steps to use custom classes in CoreData are as follows. Say you have entities A and B, where B inherits from A. Then you need two custom classes as

@interface A:NSManagedObject{
}
-(void)someMethod:(NSString*)a;
@end;
@interface B:A{
}
-(void)someMethod:(NSString*)a;
@end;

Then set them in the XCode data modeler as shown:

screenshot of XCode modeler

This way, the CoreData automatically assigns the correct class to the NSManagedObject when it is fetched from the database.

Upvotes: 26

michael23
michael23

Reputation: 3934

After trying lots of solution calling isMemberOfClass on my NSManagedObject subclass before trying to use my custom method made the trick.

[thing isMemberOfClass:[Thing class]];
[thing customMethod]; //was getting unrecognized selector sent to instance here before

Upvotes: 2

Brian R
Brian R

Reputation: 11

I had this same error for the same underlying reason, but it came about in a different situation and a different cure. Your suggestion helped me a lot!

Originally I had created my class implementing my entry by hand. I didn't know there was an Xcode menu for this. I think the link was never there! So it wasn't until I had added and began testing the new custom methods (not setter/getters) that I started to get the error.

My solution was to change the name of my class, have Xcode re-create the class for my entry via Editor->Create NS Mangage Object.... Then cut and paste in the old code into the new class. No difference in code!

Xcode seems to have some kind of internal link that is not apparent in the code.

Upvotes: 1

Alex
Alex

Reputation: 26859

If you're getting that exception, it means Core Data is not using your custom class. The key here is NSManagedObject -- that's the object Core Data created for the objects in your data store.

If you haven't already, you'll need to create a class that inherits from NSManagedObject, add your custom methods there, and then set entity A to use your custom class in the object model tool. If entities B, C, D, etc. have specific behaviors, you should subclass the class you created for entity A and assign those entities to use the subclasses too.

Essentially, you have a parallel hierarchy: one hierarchy of entities, and another of classes. You'll likely end up with entity X and class X for each entity in your object model.

Upvotes: 18

Related Questions