Question

I have privateContext with NSPrivateQueueConcurrencyType and mainContext with NSMainQueueConcurrencyType setup as below,

[self.mainContext setParentContext:self.privateContext];

With this setup I am trying to create a new managed object of my entity MyObject.

Code for this is below,

- (void)createNewObject:(void(^)(MyObject* object))block {
    [self.privateContext performBlock:^{
        MyObject *myObj = [NSEntityDescription insertNewObjectForEntityForName:@"MyObject"
                                                               inManagedObjectContext:self.privateContext];
        NSError *error = nil;
        [self.privateContext save:&error];
        if(error) {
            NSLog(@"Error in inserting object: %@", [error localizedDescription]);
        }

        //Get objectId to access it in mainContext
        NSManagedObjectID *objectId = [myObj objectID];
        [self.mainContext performBlock:^{
            if(block)
                block((MyObject*)[self.mainContext objectWithID:objectId]);
        }];
    }];
}

The block gets called on the main thread and I am also accessing the newly created object on the main thread. I check in the SQLite store and I can find this new object inserted in the table. I print this object in the block and get the following,

<MyObject: 0x140dafc0> (entity: MyObject; id: 0x11cce460 <x-coredata://BE62D8EC-66AA-4608-80F5-88B94CE3EED2/MyObject/p53> ; data: <fault>)

I have two scenarios,

  • iOS7: I can access attributes of this object.
  • iOS6.x: When I try to access any attributes from this object I get a EXC_BAD_ACCESS crash.

Why does this have different behaviour? Is there something wrong with my code?

Appreciate your help in understanding this issue.


I have tried refreshing the object when accessed from the mainContext, but still no luck.

[newObject.managedObjectContext refreshObject:newObject mergeChanges:YES]
Was it helpful?

Solution

Possibly not really a true answer, but too much for a comment...

  1. You should always check the return from save:, and then examine the error.

  2. If you have an error saving the MOC, do you really want to continue using the object?

  3. You should be using existingObjectWithID:error: instead of objectWithID: because the former returns nil if it can't be found, and an NSError indicating why. objectWithID: will always return an object... as a fault if it can't be found.

Now, this does not explain why you see the differences in iOS6/7, but I've moved on from iOS6, and can't remember all the notes I had from issues using the MOC hierarchy... and there were a lot of them in iOS5 and iOS6...

So, I suggest using existingObjectWithID:error: which should return a reasonable error as to why the object is not being retrieved in iOS6... maybe that will lead you to an immediate solution... or it may give you more information to add to the question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top