TMob
TMob

Reputation: 1278

CoreData concurrency and releasing objects

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

Answers (2)

balkaran singh
balkaran singh

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

Avi
Avi

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

Related Questions