I have a NSManagedObject subclass (SOCommand*), and I'm trying to set properties of an instance of it using the following code:
SOCommand* newCommand = [[SOCommand alloc]init];
newCommand.commandName = self.tf_commandName.text;
newCommand.sshCommand = self.tf_sshCommand.text;
However, I'm getting the error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SOCommand setCommandName:]: unrecognized selector sent to instance
I thought changing the prewritten @dynamic to @synthesize would solve it. While it did resolve this error, it led to other ones since @dynamic is required for Core Data. How am I supposed to set its properties? I read somewhere that you have to initialize NSManagedObjects in a special way, but that involved "adding" to the database, so I'm really confused.
Thanks!
~Carpetfizz
You're not showing enough code to validate this, but I suspect you are making one of several common mistakes.
Common Problem #1: Not setting up your Managed Object Model Correctly
I can't demonstrate this in code, but your managed object model must contain each property you want. Just adding a new @property declaration in the object subclass does not add it to the model. It must exist in both places.
Common Problem #2: Implementing a Getter/Setter and calling Super
- (void)setCommandName:(NSString *)commandName
{
// Do "willUpdateCommandName" logic here
//Call Super
[super setCommandName:commandName];
// Do "didUpdateCommandName" logic here
}
This is a fairly common construction outside CoreData, but within Core Data, it is a common problem. Instead, you should call the primitive setter.
- (void)setCommandName:(NSString *)commandName
{
// Do "willUpdateCommandName" logic here
//Call Super
[self setPrimitiveCommandName:commandName];
// Do "didUpdateCommandName" logic here
}
Common Problem #3: You are initializing your object with -init, rather than -initWithEntity:insertIntoManagedObjectContext:.
You are definitely making this mistake in your code sample, but possibly others too. According to the documentation, you should not use -init. Internally, I suspect that it requires the NSEntityDescription to dynamically generate the getters/setters for your object.
If you don't want the object inserted immediately, you can pass nil as the NSManagedObjectContext, but you must pass in the NSEntityDescription, acquired from your NSManagedObjectModel. Doing this correctly looks like this.
// Macro for easy reading/writing
#define SOClass(x) NSStringFromClass([x class])
// It is important to note that the entity name *CAN* be different from the class name, but generally it is not
NSString *entityName = SOClass(SOCommand);
NSDictionary *entities = self.managedObjectModel.entitiesByName;
NSEntityDescription *entityDescription = entities[entityName];
SOCommand *newCommand = [[SOCommand alloc] initWithEntity:entityDescription
insertIntoManagedObjectContext:nil];
If you know the context you want to use, you may also use this syntax:
// Macro for easy reading/writing
#define SOClass(x) NSStringFromClass([x class])
// It is important to note that the entity name *CAN* be different from the class name, but generally it is not
NSString *entityName = SOClass(SOCommand);
SOCommand *newCommand = [NSEntityDescription entityForName:entityName
inManagedObjectContext:self.managedObjectContext];
you should insert new CoreData object by using:
[NSEntityDescription insertNewObjectForEntityForName:@"SOCommand" inManagedObjectContext:self.managedObjectContext];
the way you init SOCommand cause this error .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With