I am building an application that utilizes Core Data, which has multiple entities in the Data Model. What I would like to do is create a method which is able to create the appropriate subclass of NSManagedObject based on the name that the method it receives, which would be an NSString.
My method looks like this:
- (NSManagedObject *) addEntity:(NSString *)name {
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error;
//need to add a line here that casts EntityType to of type "name" which is passed into the method.
EntityType *testEntity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
[context save:&error];
return testEntity;
}
Where "EntityType" is of type "name", such that if I pass the name "Manager" into the method, I will create an object of type "Manager". Therefore the above line:
EntityType *testEntity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
would read:
Manager *testEntity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
What do I need to do in order to dynamically create Entities based on the type that I pass into the method? Please note that I am doing this because I have over twenty entities in my application and would like to have just one method that I can use for any of them.
If your issue is the type of testEntity
just use a generic NSManagedObject
Anyway a nice solution would be to add a category over NSManagedObject
. Here's an implementation which basically replicates the same functionality provided by MagicalRecord.
NSManagedObject+Utilities.h
@interface NSManagedObject (Utilities)
+ (instancetype)my_createAndSave:(NSError **)error;
@end
NSManagedObject+Utilities.m
@implementation NSManagedObject (Utilities)
+ (instancetype)my_createAndSave:(NSError **)error {
NSString *entityName = NSStringFromClass(self);
if ([self respondsToSelector:@selector(entityName)]) {
entityName = [self performSelector:@selector(entityName)];
}
NSManagedObject *entity = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.managedObjectContext];
[self.managedObjectContext save:error];
return entity;
}
@end
A few remarks:
Naming:
- being a category is always preferable to add a custom prefix, not to clash with Apple's API. I used
my_
here, but you can add whatever you like.
- starting the method name with
new
should be reserved to method returning a non autoreleased object. Since entity
is autoreleased, ARC will add an extra retain
before returning the object (balanced later by a release
) (reference). While this is not an issue, it breaks the standard naming conventions and should be avoided.
Error handling
- you should either yield the error or handle it properly. I chose to pass the error back to the caller in my implementation