iOS CoreData+MoGenerator : How do I initialize a Managed Object once only when I am using nested contexts?

标签 ios core-data mogenerator

我正在使用 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 中所做的初始化更改不存在。 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 结构时,初始化托管对象的正确位置是什么?

最佳答案

关于awakeFromInsert 的文档有些过时并且没有反射(reflect)嵌套上下文的现实。当它说方法是

Invoked automatically by the Core Data framework when the receiver is first inserted into a managed object context.

它真的应该说“..first inserted into any managed object context”,因为(如您所见)嵌套上下文不止一次发生这种情况。实际上,awakeFromInsert 的概念在使用嵌套上下文时有点过时了。该方法显然是在过去的非嵌套时代设计的,尚未适应。

有几种方法可以解决这个问题。一种是简单的运行时检查,您可以执行以下操作:

if ([[self managedObjectContext] parentContext] != nil) {
    // Set default values here
}

此代码仅在当前上下文是其他上下文的子上下文时运行。该方法仍然为父上下文运行,但您跳过了默认值 setter 。如果您只嵌套一层,那很好,即一个父级具有一个或多个子上下文,但没有父级的“孙子”上下文。如果您添加了另一个嵌套级别,您就回到了起点。

另一种选择(也是我通常更喜欢的一种)是将默认值代码移到一个单独的方法中,然后根本不使用 awakeFromInsert。也就是说,创建一个名为 setDefaultValues 的方法,在您的情况下,它会设置 syncStatusValuetempObjectPID 的值。 在您第一次创建新实例后立即调用此方法,而不是在其他任何地方。由于它永远不会收到自动调用,因此除非您告诉它运行,否则代码永远不会运行。

关于iOS CoreData+MoGenerator : How do I initialize a Managed Object once only when I am using nested contexts?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19144517/

相关文章:

ios - 为 objective-c 中的指定字符串创建正则表达式

iphone - 不允许在 prepareForDeletion 中执行获取请求?

ios - 如何在 Swift 中从数据库中保存和获取一个对象?

objective-c - 扩展核心数据生成的 NSManagedObject 类

ios - SK节点!不可转换为 "SKNode"

ios - Tiled - 支持不同的ios设备

objective-c - NSManagedObjectContext,在哪里声明?

objective-c - 我如何使用 MOgenerator 的 xmod?

iphone - 标签在横向模式下无法正确对齐