Reputation: 1278
I'm currently validating our new CoreData architecture which is being used in a multi-threaded environment. For analyzing I'm using GDCoreDataConcurrencyDebugging which prints a warning, every time a ManagedObject is accessed from the wrong thread / queue (as far as I understood).
Now I'm getting tons of warnings like this:
Invalid concurrent access to managed object calling 'release'
I was able to put a break-point where the warning is generated and the code looks like this:
-(MyObject*) createMyObject {
return (MyObject*)[self insertNewObjectEntityWithName:@"MyObject"];
}
-(NSManagedObject*) insertNewObjectEntityWithName:(NSString*) entityName {
__block NSManagedObject *managedObject;
[self.managedObjectContext performBlockAndWait:^(void) {
managedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName
inManagedObjectContext:self.managedObjectContext];
}];
return managedObject;
}
Its breaking in the createMyObject
-method after the return, which I guess is when the objects are being released. Is there anything special I missed with CoreData-concurrency and object-release?
I've looked around and there isn't anything being mentioned about object-release, only about autoreleasepools which I'm not using.
Upvotes: 0
Views: 64
Reputation: 2786
plz use this code to get managedObjectContext .managed objects must be accessed from the thread/queue on which they are created.
- (NSManagedObjectContext *)managedObjectContext
{
NSThread *thisThread = [NSThread currentThread];
if (thisThread == [NSThread mainThread])
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
//
if ([self persistentStoreCoordinator] != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
}
[_managedObjectContext setRetainsRegisteredObjects:YES];
[_managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
return _managedObjectContext;
}
else
{
//Return separate MOC for each new thread
NSManagedObjectContext *threadManagedObjectContext = [[thisThread threadDictionary] objectForKey:@"MOC_KEY"];
if (threadManagedObjectContext == nil)
{
threadManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
[threadManagedObjectContext setPersistentStoreCoordinator: coordinator];
[[thisThread threadDictionary] setObject:threadManagedObjectContext forKey:@"MOC_KEY"];
}
return threadManagedObjectContext;
}
}
Upvotes: 0
Reputation: 7552
You are performing the work in a performBlockAndWait:
call, which is correct. However, you proceed to return the object, presumably from a different thread. That is not legal. All managed objects must be accessed from the thread/queue on which they are created, with the exception of the objectID
property, which is always valid.
Upvotes: 2