Created
April 15, 2011 20:55
-
-
Save patcoll/922466 to your computer and use it in GitHub Desktop.
This file contains 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 characters
#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 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 characters
// 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]; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment