0

I use core data like this:

- (NSManagedObjectContext *)managedObjectContext {
@synchronized(self) {
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [NSManagedObjectContext new];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
}

return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel {
@synchronized(self) {
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSString *path = [[NSBundle mainBundle] pathForResource:@"DB" ofType:@"momd"];
    if (path) {
        NSURL *momURL = [NSURL fileURLWithPath:path];
        _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
    }
}

return _managedObjectModel;
}

But sometimes i have crash: Collection <__NSCFSet: 0x14c5bffdq> was mutated while being enumerated. What wrong? How to use core data with multithreading?

Flexoid
  • 50
  • 8

2 Answers2

0

This crash occurs when you are mutating or changing a core data entity while in a for loop or while loop. Something like this

    for(NSManageObject *obj in someArray){
        [context deleteObject:someArray];
   }

You might have to change your logic as to what you want to achieve, because of the crash.

Now if you want to perform Core data in background mode, there are certain ways to do that.

  • Parent-child context is one of them, where you create a child context and do all the work in the performBlock and push the save changes as it automatically pushes the changes back to the parent MOC.

  • Operate in a async singleton queue but perform changes or saveContext in the main queue. You can also swap queue with NSOperationQueue, and create a singleton. This way you can perform Core Data operations in background as you Dont freeze your UI.

All depends on what you want to do and what is it you are trying to achieve. On a broader aspect I would suggest to go for Parent-Child context. It is robust and would solve your issue of Core Data multithreading.

EDIT -

Please check out this answer for a correct implementation for parent-child context in Core data.

Community
  • 1
  • 1
Saheb Roy
  • 5,899
  • 3
  • 23
  • 35
  • Parent-child context: please help, how to do this – Flexoid Jun 24 '16 at 12:22
  • for(NSManageObject *obj in someArray){ [context deleteObject:someArray]; } In this example, we need to use child context? – Flexoid Jun 24 '16 at 12:33
  • and if i do save after delete [self.managedObjectContext save:&error], app stop crashing? – Flexoid Jun 24 '16 at 12:44
  • A better solution would be to keep all the objects you want to delete in an array and then delete all the objects at once. – Saheb Roy Jun 24 '16 at 13:01
  • I have another crash: EXC_BAD_ACCESS KERN_INVALID_ADDRESS when i change nsmanagedobject property. What is problem here? – Flexoid Jun 24 '16 at 13:24
0
*- (NSManagedObjectContext *)managedObjectContext
{
    DDLogTrace();
    if (__managedObjectContext != nil) {
        return __managedObjectContext;
    }

    dispatch_block_t initBlock = ^{
        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (coordinator != nil) {
            __managedObjectContext = [[NSManagedObjectContext alloc] init];


        }
    };

    if ([NSThread isMainThread]) {
        initBlock();
    }else{
        dispatch_sync(dispatch_get_main_queue(), initBlock);
    }

    return __managedObjectContext;
}*


Try this , many time thread swich and   NSManagedObjectContext create in secondary or background thread .
NSManagedObjectContext always execute in main thread