将@dynamic与Core Data一起使用时,无法识别的选择器被发送到实例

Car*_*izz 2 core-data objective-c ios

我有一个NSManagedObject子类(SOCommand*),我正在尝试使用以下代码设置它的实例的属性:

    SOCommand* newCommand = [[SOCommand alloc]init];
    newCommand.commandName = self.tf_commandName.text;
    newCommand.sshCommand = self.tf_sshCommand.text;
Run Code Online (Sandbox Code Playgroud)

但是,我收到错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SOCommand setCommandName:]: unrecognized selector sent to instance
Run Code Online (Sandbox Code Playgroud)

我想改变预先写入@dynamic@synthesize会解决这个问题.虽然它确实解决了这个错误,但由于@dynamicCore Data需要,它导致了其他错误.我该怎么设置它的属性?我在某处读到你必须以NSManagedObjects特殊方式初始化,但这涉及"添加"到数据库,所以我真的很困惑.

谢谢!

〜Carpetfizz

Hol*_*lly 11

您没有显示足够的代码来验证这一点,但我怀疑您正在犯下几个常见错误之一.

常见问题#1:未正确设置托管对象模型我无法在代码中证明这一点,但您的托管对象模型必须包含您想要的每个属性.只@property在对象子类中添加新声明不会将其添加到模型中.它必须存在于两个地方.

常见问题#2:实现Getter/Setter并调用Super

- (void)setCommandName:(NSString *)commandName
{
    // Do "willUpdateCommandName" logic here

    //Call Super
    [super setCommandName:commandName];

    // Do "didUpdateCommandName" logic here
}
Run Code Online (Sandbox Code Playgroud)

这是CoreData外部相当常见的构造,但在Core Data中,这是一个常见问题.相反,你应该调用原始setter.

- (void)setCommandName:(NSString *)commandName
{
    // Do "willUpdateCommandName" logic here

    //Call Super
    [self setPrimitiveCommandName:commandName];

    // Do "didUpdateCommandName" logic here
}
Run Code Online (Sandbox Code Playgroud)

常见问题#3:您正在使用-init而不是初始化对象-initWithEntity:insertIntoManagedObjectContext:.

您肯定在代码示例中犯了这个错误,但也可能是其他错误.根据文档,你不应该使用-init.在内部,我怀疑它需要NSEntityDescription动态生成对象的getter/setter.

如果你不想对象立即插入,则可以通过nil作为NSManagedObjectContext,但你必须传递NSEntityDescription,从你的收购NSManagedObjectModel.正确地执行此操作就像这样.

// 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];
Run Code Online (Sandbox Code Playgroud)

如果您知道要使用的上下文,也可以使用以下语法:

// 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];
Run Code Online (Sandbox Code Playgroud)


joh*_*nMa 7

您应该使用以下方法插入新的CoreData对象:

[NSEntityDescription insertNewObjectForEntityForName:@"SOCommand" inManagedObjectContext:self.managedObjectContext];
Run Code Online (Sandbox Code Playgroud)

你初始化SOCommand导致这个错误的方式.