I try to do the following simple thing:
NSArray * entities = [context executeFetchRequest:inFetchRequest error:&fetchError];
Nothing fancy. But this freezes in iOS 5, it works fine in iOS 4. I don't get exceptions, warnings or errors; my app just simply freezes.
Please help me out! I'm dying here! ;)
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.
Maybe this article can help you : http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/
Apple has a demo application for handling Coredata on several threads (usually main & background threads) : http://developer.apple.com/library/ios/#samplecode/TopSongs/Introduction/Intro.html
What I've done to solve this issue is :
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.
in the application delegate :
-(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:&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:&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]; } }
In the object running the background thread :
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]; ... } }
Hope this help,
M.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With