Created
April 15, 2011 20:55
Revisions
-
patcoll created this gist
Apr 15, 2011 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,10 @@ #define SYNC_INTERVAL 60 @interface AppDelegate : NSObject <UIApplicationDelegate> { // ... NSMutableDictionary *mocs; NSMutableDictionary *mocThreads; // ... } @property (nonatomic, retain) NSMutableDictionary *mocs; @property (nonatomic, retain) NSMutableDictionary *mocThreads; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,132 @@ // put this somewhere in @implementation: // @synthesize mocs, mocThreads; - (void)awakeFromNib { [NSTimer scheduledTimerWithTimeInterval:SYNC_INTERVAL target:self selector:@selector(sync) userInfo:nil repeats:YES]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(threadWillExit:) name:NSThreadWillExitNotification object:nil]; } - (void) sync { [self performSelectorInBackground:@selector(doSync) withObject:nil]; } - (void) doSync { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSManagedObjectContext *ctx = [self managedObjectContext]; // sync! ctx will be a fresh MOC within a new thread [pool release]; } - (void) threadWillExit:(NSNotification *)notification { NSThread *exitingThread = [notification object]; [self destroyManagedObjectContextForThreadName:[exitingThread name]]; } - (void) mergeChanges:(NSNotification *)notification { // Merge changes from the MOC that sent the notification to all other MOCs in all other threads. NSManagedObjectContext *mocThatSentNotification = [notification object]; [mocs enumerateKeysAndObjectsUsingBlock:^(id name, id moc, BOOL *stop) { name = (NSString *)name; moc = (NSManagedObjectContext *)moc; NSThread *thread = [mocThreads objectForKey:name]; // don't send notifications back to the MOC that sent it. if (![moc isEqual:mocThatSentNotification]) { // waitUntilDone:NO because the thread could exit prematurely -- and we don't really care why. [moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:) onThread:thread withObject:notification waitUntilDone:NO]; } }]; } // ... /** Returns the managed object context for the current thread. If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application. */ - (NSManagedObjectContext *)managedObjectContext { if (mocs == nil) { self.mocs = [[NSMutableDictionary alloc] init]; } if (mocThreads == nil) { self.mocThreads = [[NSMutableDictionary alloc] init]; } static int counter = 0; NSThread *current = [NSThread currentThread]; if ([current name] != nil && [mocs objectForKey:[current name]] != nil) { return [mocs objectForKey:[current name]]; } [current setName:[NSString stringWithFormat:@"%d", ++counter]]; NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; [moc setPersistentStoreCoordinator:coordinator]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:moc]; [mocs setObject:moc forKey:[current name]]; [mocThreads setObject:current forKey:[current name]]; } return [mocs objectForKey:[current name]]; } - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { // return a valid NSPersistentStoreCoordinator } - (NSString *) mainThreadName { NSSet *mainThreadNameSet = [mocThreads keysOfEntriesWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id key, id obj, BOOL *stop) { return [obj isEqual:[NSThread mainThread]]; }]; return [mainThreadNameSet anyObject]; } - (NSManagedObjectContext *)mainManagedObjectContext { [self managedObjectContext]; return [mocs objectForKey:[self mainThreadName]]; } - (void) destroyManagedObjectContextForThreadName:(NSString *)name { if (name != nil && [mocs objectForKey:name] != nil) { NSManagedObjectContext *moc = [mocs objectForKey:name]; [moc release]; moc = nil; [mocs removeObjectForKey:name]; [mocThreads removeObjectForKey:name]; } } - (void) destroyAllManagedObjectContexts { for (NSString *name in [mocs allKeys]) { [self destroyManagedObjectContextForThreadName:name]; } }