Skip to content

Instantly share code, notes, and snippets.

@patcoll
Created April 15, 2011 20:55
Show Gist options
  • Save patcoll/922466 to your computer and use it in GitHub Desktop.
Save patcoll/922466 to your computer and use it in GitHub Desktop.
#define SYNC_INTERVAL 60
@interface AppDelegate : NSObject <UIApplicationDelegate> {
// ...
NSMutableDictionary *mocs;
NSMutableDictionary *mocThreads;
// ...
}
@property (nonatomic, retain) NSMutableDictionary *mocs;
@property (nonatomic, retain) NSMutableDictionary *mocThreads;
// 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