Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I don't know if you also use different Thread. If yes the issue comes from the fact that NSManagedObjects themselves are not thread-safe. Creating a ManagedContext on the main thread and using it on another thread freezes the thread.</p> <p>Maybe this article can help you : <a href="http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/" rel="noreferrer">http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/</a></p> <p>Apple has a demo application for handling Coredata on several threads (usually main &amp; background threads) : <a href="http://developer.apple.com/library/ios/#samplecode/TopSongs/Introduction/Intro.html" rel="noreferrer">http://developer.apple.com/library/ios/#samplecode/TopSongs/Introduction/Intro.html</a></p> <p>What I've done to solve this issue is :</p> <ul> <li>In the application delegate : create the persistent store (one for all thread) and create the Coredata managed Context for the main thread,</li> <li>In the background thread, create a new managed context (from same persistent store)</li> <li>Notifications are used when saving, to let the mainContext know when background thread has finished (inserting rows or other).</li> </ul> <p>There are several solutions, using a NSQueueOperation. For my case, I'm working with a while loop. Here is my code if it may help you. However, Apple documentation on concurrency and their Top Songs example application are good points to start.</p> <p>in the application delegate :</p> <pre><code> -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.cdw = [[CoreDataWrapper alloc] initWithPersistentStoreCoordinator:[self persistentStoreCoordinator] andDelegate:self]; remoteSync = [RemoteSync sharedInstance]; ... [self.window addSubview:navCtrl.view]; [viewController release]; [self.window makeKeyAndVisible]; return YES; } - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (persistentStoreCoordinator == nil) { NSURL *storeUrl = [NSURL fileURLWithPath:self.persistentStorePath]; NSLog(@"Core Data store path = \"%@\"", [storeUrl path]); persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]]; NSError *error = nil; NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&amp;error]; NSAssert3(persistentStore != nil, @"Unhandled error adding persistent store in %s at line %d: %@", __FUNCTION__, __LINE__, [error localizedDescription]); } return persistentStoreCoordinator; } -(NSManagedObjectContext *)managedObjectContext { if (managedObjectContext == nil) { managedObjectContext = [[NSManagedObjectContext alloc] init]; [managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; } return managedObjectContext; } -(NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (persistentStoreCoordinator == nil) { NSURL *storeUrl = [NSURL fileURLWithPath:self.persistentStorePath]; NSLog(@"Core Data store path = \"%@\"", [storeUrl path]); persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]]; NSError *error = nil; NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&amp;error]; NSAssert3(persistentStore != nil, @"Unhandled error adding persistent store in %s at line %d: %@", __FUNCTION__, __LINE__, [error localizedDescription]); } return persistentStoreCoordinator; } -(NSManagedObjectContext *)managedObjectContext { if (managedObjectContext == nil) { managedObjectContext = [[NSManagedObjectContext alloc] init]; [managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; } return managedObjectContext; } -(NSString *)persistentStorePath { if (persistentStorePath == nil) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths lastObject]; persistentStorePath = [[documentsDirectory stringByAppendingPathComponent:@"mgobase.sqlite"] retain]; } return persistentStorePath; } -(void)importerDidSave:(NSNotification *)saveNotification { if ([NSThread isMainThread]) { [self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification]; } else { [self performSelectorOnMainThread:@selector(importerDidSave:) withObject:saveNotification waitUntilDone:NO]; } } </code></pre> <p>In the object running the background thread : </p> <pre><code>monitor = [[NSThread alloc] initWithTarget:self selector:@selector(keepMonitoring) object:nil]; -(void)keepMonitoring{ while(![[NSThread currentThread] isCancelled]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; AppDelegate * appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; //creating the cdw here will create also a new managedContext on this particular thread cdwBackground = [[CoreDataWrapper alloc] initWithPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator andDelegate:appDelegate]; ... } } </code></pre> <p>Hope this help,</p> <p>M.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload