初始化托管对象而不插入托管对象上下文时,核心数据对象属性为零
Posted
技术标签:
【中文标题】初始化托管对象而不插入托管对象上下文时,核心数据对象属性为零【英文标题】:Core Data object properties are nil when Managed Object is initialized WITHOUT inserting into a Managed Object Context 【发布时间】:2016-05-18 19:09:17 【问题描述】:在我的 Core Data 应用程序中,我使用 initWithEntity:insertIntoManagedObjectContext:
和 nil
上下文初始化托管对象。然后我使用[managedObjectContext insertObject:object]
将对象插入到上下文中,如果/需要的话。
看来这就是insertObject:
API 存在的原因。插入在创建期间未插入的托管对象。
但是当使用上述逻辑时,对象(稍后从 MOC 获取时)具有 nil 属性。对象上的字符串不会被持久化。
如果我将 initWithEntity:insertIntoManagedObjectContext:
与 non-nil MOC 一起使用,则属性 会保持不变并且一切正常。在这种情况下,我不打电话给insertObject:
。
代码的两个变体如下。只需切换useNilContext
标志即可尝试每个。
// ...
BOOL useNilContext = YES;
[[XYZBackend sharedBackend].managedObjectContextPrivateQueue performBlock:^
XYZObject *object = [XYZObject objectFromJSON:json useNilContext:useNilContext];
if (useNilContext)
[[XYZBackend sharedBackend].managedObjectContextPrivateQueue insertObject:object];
NSError *privateQueueError = nil;
if (![[XYZBackend sharedBackend].managedObjectContextPrivateQueue save:&privateQueueError])
NSLog(@"Error saving Core Data managed object context in private queue! %@", privateQueueError);
];
// ...
+ (instancetype)managedObjectFromJSON:(NSDictionary *)json useNilContext:(BOOL)useNilContext
__block XYZManagedObject *object = nil;
[[XYZBackend sharedBackend].managedObjectContextPrivateQueue performBlockAndWait:^
NSEntityDescription *entity = [NSEntityDescription entityForName:NSStringFromClass([self class]) inManagedObjectContext:[XYZBackend sharedBackend].managedObjectContextPrivateQueue];
NSManagedObjectContext *context = [XYZBackend sharedBackend].managedObjectContextPrivateQueue;
if (useNilContext)
context = nil;
object = [[XYZManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
object.stringProperty = json[@"string"];
];
return object;
稍后,当我从 Core Data 获取对象并检查它时,我会得到不同的行为,具体取决于对象最初是否插入到 MOC 中。如果 MOC 是nil
,那么在获取之后对象的所有属性都是nil
。
将initWithEntity:insertIntoManagedObjectContext:
与nil
MOC 一起使用:
Printing description of object:
<XYZObject: 0x60b0000b80d0> (entity: XYZObject; id: 0xd000000000040000 <x-coredata://5F843602-C03B-4339-AC50-0F70FD1545C9/XYZObject/p1> ; data:
stringProperty = nil;
)
使用非零 MOC 初始化:
Printing description of object:
<XYZObject: 0x60b000054680> (entity: XYZObject; id: 0xd000000000040000 <x-coredata://72502855-7204-4485-828C-BC07C51F7FE2/XYZObject/p1> ; data:
stringProperty = "string";
)
如您所见,当对象最初未插入 MOC 时,获取后的属性为 nil
。当它最初被插入到 MOC 中时,属性是非 nil 并且是持久的。
为什么这些属性没有持久化?我认为这两种代码策略应该是相同的。
是否必须采取另一个步骤来保持最初具有nil
托管对象上下文的托管对象的属性?
【问题讨论】:
您是否尝试过在设置对象 stringProperty 之前和之后检查它。它实际上是在两种情况下都设置的吗? 【参考方案1】:不,没有额外的步骤。至于为什么不保存属性,您的代码中还有其他原因导致了问题。无论您提供上下文还是使用 nil 上下文但随后插入对象,分配新托管对象的工作方式都相同。
看起来您可能混淆了上下文,但很难确定。当您调用insert:
时,您使用[TDBackend sharedBackend].managedObjectContextPrivateQueue
。但是当您保存更改时,您使用self.managedObjectContextPrivateQueue
。同时,当useNilContext
为NO
时,您使用[XYZBackend sharedBackend].managedObjectContextPrivateQueue
创建托管对象。您正在与[ZYZBackend sharedBackend].managedObjectContextPrivateQueue
上的块调用同步。这是一段相当简单的代码中的四种不同的上下文。无法确定,但它给人的印象是您在某些时候使用了错误的上下文
【讨论】:
谢谢,这些是我为这个问题编写的上述伪代码中的拼写错误。已更正。应该只使用单个[XYZBackend sharedBackend].managedObjectContextPrivateQueue
我的真实版本是使用单个私有上下文(和主上下文)。以上是关于初始化托管对象而不插入托管对象上下文时,核心数据对象属性为零的主要内容,如果未能解决你的问题,请参考以下文章