- (void)awakeFromInsert { [super awakeFromInsert]; NSManagedObjectContext *context = [self managedObjectContext]; self.name = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context]; }
这在单个非嵌套管理对象上下文中工作得很好.但是,如果上下文具有父上下文,则当保存子上下文时,将在父上下文中创建一个新的Person对象,并且在原始Person的属性和关系被复制之前,再次调用此新对象的-awakeFromInsert.因此,创建另一个Name对象,然后在现有的名称关系复制时“断开连接”.保存失败,因为验证浮动名称现在无关联关系失败.这个问题描述在here以及其他地方.
到目前为止,我无法想出这个问题的一个很好的解决方案.在getter方法中懒洋洋地创建关系实际上会导致同样的问题,因为当在父上下文中创建新Person时,内部Core Data机器调用getter.
我唯一可以想出的是放弃自动关系生成,并且始终在创建Person的控制器类中明确创建关系,或者在一个方便的方法(例如[Person insertNewPersonInManagedObjectContext:])中创建关系,这个方法只能被我的代码,并且始终是用于显式创建新Person对象的方法.也许这是最好的解决方案,但是我宁可不必那么严格,只允许使用单一的方法来创建管理对象,当我无法控制的其他创建方法,我无法使用它容易检查/排除,存在.首先,它将意味着多个NSArrayController子类来自定义他们创建管理对象的方式.
遇到这个问题的其他任何人都想出了一个优雅的解决方案,允许一个NSManagedObject在创建/插入时自动创建关系对象?
解决方法
如果没有,一个简单的方法就是在创建一个名字之前检查你是否在根上下文中:
- (void)awakeFromInsert { [super awakeFromInsert]; NSManagedObjectContext *context = [self managedObjectContext]; if ([context parentContext] != nil) { self.name = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context]; } }
但是,如果您始终在子上下文中创建新实例,并且您不会嵌套多于一个级别的上下文,那么该方法才起作用.
我可能会做的是创建一个方法,如insertNewPersonInManagedObjectContext:你描述的.然后用以下内容补充以处理为您创建实例(即数组控制器)的任何情况:
- (void)willSave { if ([self name] == nil) { NSManagedObjectContext *context = [self managedObjectContext]; Name *name = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context]; [self setName:name]; } }
…当然不用打扰自定义awakeFromInsert …