我正在使用mogenerator从具有TestPerson托管对象的模型生成代码。 TestPerson继承自抽象对象TLSyncParent。在TLSyncParent中我有代码:
- (void) awakeFromInsert
{
[super awakeFromInsert];
QNSLOG(@"%@\n%@", self.managedObjectContext, self.description);
if (self.syncStatus == nil) {
self.syncStatusValue = SYNCSTATUS_NEW;
self.tempObjectPID = [self generateUUID];
QNSLOG(@"After init values\n%@", self.description);
}
}
我在childMOC中创建了TestPerson对象,其父级是mainMOC,其父级是rootMOC。 awakeFromInsert按预期运行并进行init更改。当我将childMOC保存到mainMOC时,再次运行awakeFromInsert。从我不希望的文档,但有一些模棱两可。从文档"您通常使用此方法初始化特殊的默认属性值。此方法仅在对象的生命周期内调用一次。"真正的问题是当awakeFromInsert在mainMOC中运行时,在childMOC中进行的init更改不存在。 awakeFromInsert显然在实际保存之前运行。
2013-10-02 11:22:45.510_xctest[21631:303] TestPerson -awakeFromInsert <NSManagedObjectContext: 0xd684780>
<TestPerson: 0xd6863b0> (entity: TestPerson; id: 0xd684ed0 <x-coredata:///TestPerson/t02B71E0D-AE3F-4605-8AC7-638AE072F2302> ; data: {
dept = nil;
job = nil;
objectPID = nil;
personName = nil;
syncStatus = 0;
tempObjectPID = nil;
updatedAt = nil;
})
2013-10-02 11:22:45.511_xctest[21631:303] TestPerson -awakeFromInsert After init values
<TestPerson: 0xd6863b0> (entity: TestPerson; id: 0xd684ed0 <x-coredata:///TestPerson/t02B71E0D-AE3F-4605-8AC7-638AE072F2302> ; data: {
dept = nil;
job = nil;
objectPID = nil;
personName = nil;
syncStatus = 4;
tempObjectPID = "7AB46623-C597-4167-B189-E3AAD24954DE";
updatedAt = nil;
})
2013-10-02 11:22:45.511_xctest[21631:303] CoreDataController -saveChildContext: Saving Child MOC
2013-10-02 11:22:45.511_xctest[21631:303] TestPerson -awakeFromInsert <NSManagedObjectContext: 0xd682180>
<TestPerson: 0xd68fce0> (entity: TestPerson; id: 0xd684ed0 <x-coredata:///TestPerson/t02B71E0D-AE3F-4605-8AC7-638AE072F2302> ; data: {
dept = nil;
job = nil;
objectPID = nil;
personName = nil;
syncStatus = 0;
tempObjectPID = nil;
updatedAt = nil;
})
2013-10-02 11:22:45.511_xctest[21631:303] TestPerson -awakeFromInsert After init values
<TestPerson: 0xd68fce0> (entity: TestPerson; id: 0xd684ed0 <x-coredata:///TestPerson/t02B71E0D-AE3F-4605-8AC7-638AE072F2302> ; data: {
dept = nil;
job = nil;
objectPID = nil;
personName = nil;
syncStatus = 4;
tempObjectPID = "B799AFDA-3514-445F-BB6F-E4FE836C4F9D";
updatedAt = nil;
})
使用MoGenerator结构时初始化托管对象的适当位置是什么?
答案 0 :(得分:4)
awakeFromInsert
上的文档有点过时,并不反映嵌套上下文的实际情况。当它说方法是
当接收器首次插入托管对象上下文时,由Core Data框架自动调用。
它应该说“首先插入任何托管对象上下文”,因为(正如您所发现的)这种情况不止一次发生在嵌套上下文中。实际上,awakeFromInsert
的概念在使用嵌套上下文时有点过时了。该方法在旧的非嵌套日期中进行了明确设计,并未进行调整。
有几种方法可以解决这个问题。一个是简单的运行时检查,您可以执行以下操作:
if ([[self managedObjectContext] parentContext] != nil) {
// Set default values here
}
此代码仅在当前上下文是某些其他上下文的子项时运行。该方法仍然针对父上下文运行,但是您跳过了默认值设置器。如果您只嵌套一个级别,即一个父级具有一个或多个子上下文,但没有父级的“孙子”上下文,那就没问题。如果你曾经添加过另一个嵌套级别,那么你就可以回到起点。
另一个选项(以及我通常喜欢的选项)是将默认值代码移动到单独的方法中,然后根本不使用awakeFromInsert
。也就是说,创建一个名为setDefaultValues
的方法,在您的情况下设置syncStatusValue
和tempObjectPID
的值。 在您首次创建新实例后立即调用此方法,而不是其他地方。由于它永远不会自动调用,因此代码永远不会运行,除非您告诉它运行。
答案 1 :(得分:1)
我很确定Mogenerator不会改变创建托管对象的方式,但只会将实际的托管对象类移动到带有“_”前缀的机器生成的文件,并创建这些托管对象的子类以放置所有自定义逻辑输入,以便在重新生成托管对象类时不会丢失。
答案 2 :(得分:-3)
好的,感谢Tom Herrington,我找到了一个很好的方法来做到这一点。它似乎完全符合我的要求而且遇到了麻烦。它完全符合MoGenerator结构。我已经使用initWithMOC方法在NSManagedObject上有一个类别。我添加了对方法awakeFromCreate的调用并提供了一个默认实现。您只需覆盖awakeFromCreate,就像覆盖awakeFromInsert一样。唯一的要求是你总是使用initWithMOC方法创建MO。
@implementation NSManagedObject (CoreDataController)
+ (NSManagedObject*) initWithMOC: (NSManagedObjectContext*) context
{
NSManagedObject* mo = (NSManagedObject*)
[NSEntityDescription insertNewObjectForEntityForName: NSStringFromClass(self)
inManagedObjectContext: context];
[mo awakeFromCreate];
return mo;
}
- (void) awakeFromCreate
{
return;
}