In my Core Data app I am initializing Managed Objects using initWithEntity:insertIntoManagedObjectContext:
with a nil
Context. I'm then using [managedObjectContext insertObject:object]
to insert the object into the Context, if/when needed.
It seems that this is why the insertObject:
API exists. To insert a Managed Object that was not inserted during creation.
But when the above logic is used, the objects (when later fetched from the MOC) have nil properties. The strings on the object are not persisted.
If I instead use initWithEntity:insertIntoManagedObjectContext:
with a non-nil MOC, the properties are persisted and everything works correctly. In this case, I do not call insertObject:
.
The two variances of the code are below. Simply toggle the useNilContext
flag to try each.
// ...
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;
}
Later, when I fetch the object from Core Data and inspect it, I get different behavior depending on if the object was initially inserted into a MOC. If the MOC was nil
, all of the object's properties are nil
after the fetch.
Using initWithEntity:insertIntoManagedObjectContext:
with a nil
MOC:
Printing description of object:
<XYZObject: 0x60b0000b80d0> (entity: XYZObject; id: 0xd000000000040000 <x-coredata://5F843602-C03B-4339-AC50-0F70FD1545C9/XYZObject/p1> ; data: {
stringProperty = nil;
})
Initializing with a non-nil MOC:
Printing description of object:
<XYZObject: 0x60b000054680> (entity: XYZObject; id: 0xd000000000040000 <x-coredata://72502855-7204-4485-828C-BC07C51F7FE2/XYZObject/p1> ; data: {
stringProperty = "string";
})
As you can see, the properties are nil
after the fetch when the object was not initially inserted into a MOC. When it is initially inserted into the MOC, the properties are non-nil and persisted.
Why are these properties not persisted? I would think that the two code strategies should be identical.
Is there another step that must be taken to persist the properties of a Managed Object that initially has a nil
Managed Object Context?