Last active
December 17, 2015 16:29
-
-
Save puppybits/5638851 to your computer and use it in GitHub Desktop.
Core Data FreezeDry. Add Multithreading API to the NSManagedObject to share/pass between threads, with either sync or async GCD dispatch queues.
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 characters
// | |
// CoreData+FreezeDry.h | |
// Streamlines transfering a single core data entity between treads. | |
// This WILL run SLOW with lots of data. | |
// Minimize changing threads! | |
// Use it on single objects. | |
// Use it as an example to batch transfer a large set of data. | |
// | |
// Created by Bobby Schultz on 1/13/12. | |
// | |
// @example: | |
// __block NSManagedObjectID *frozenID = myModel.slowFreezeDry; | |
// | |
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ | |
// | |
// NSManagedObjectContext *backgroundContext = [NSManagedObjectContext initContextForCurrentThread]; | |
// MyObject *myBackgroundModel = (MyObject*)[frozenID slowRehydrateWithContext:backgroundContext]; | |
// | |
// [myBackgroundModel updateFromSlowWebService]; | |
// | |
// frozenID = myBackgroundModel.slowFreezeDry; | |
// dispatch_async(dispatch_get_main_queue(), ^{ | |
// MyObject *myMainModel = (MyObject*)[frozenID slowRehydrateWithContext:appDelegate.moc]; | |
// [self refreshView]; | |
// }); | |
// } | |
// | |
// [threadContext release]; | |
// }); | |
// | |
#import <CoreData/CoreData.h> | |
@interface NSManagedObjectID (FreezeDry) | |
- (NSManagedObject*) slowRehydrateWithContext:(NSManagedObjectContext*)context; | |
@end | |
@interface NSManagedObject (FreezeDry) | |
- (NSManagedObjectID*) slowFreezeDry; | |
@end | |
@interface NSManagedObjectContext (FreezeDry) | |
+ (NSManagedObjectContext*) initContextForCurrentThread; | |
@end |
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 characters
// | |
// CoreData+FreezeDry.m | |
// | |
// Created by Bobby Schultz on 1/13/12. | |
// | |
#import "CoreData+FreezeDry.h" | |
@implementation NSManagedObjectID (FreezeDry) | |
- (NSManagedObject*) slowRehydrateWithContext:(NSManagedObjectContext*)context | |
{ | |
// Reload the frozen object | |
NSManagedObject* obj; | |
obj = [context objectWithID:self]; | |
// Make sure it doesn't have brain damage | |
if (obj == nil || obj.entity == nil) return nil; | |
// Make sure its fully thawed | |
if ([obj isFault]) | |
{ | |
NSError *error = nil; | |
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = %@", obj]; | |
NSFetchRequest *fetcher = [NSFetchRequest fetchRequestWithEntityName:obj.entity.name]; | |
[fetcher setPredicate:predicate]; | |
// Load it into the managed context for this thread | |
NSArray *results = [context executeFetchRequest:fetcher error:&error]; | |
// Make sure it's really there | |
if(results == nil || results.count == 0) | |
return nil; | |
// Set object so it can be returned to the land of the living | |
obj = [results objectAtIndex:0]; | |
} | |
// Done and done | |
return obj; | |
} | |
@end | |
@implementation NSManagedObject (FreezeDry) | |
- (NSManagedObjectID*) slowFreezeDry | |
{ | |
// Make sure it's shareable across threads | |
BOOL isMain = (dispatch_get_current_queue() == dispatch_get_main_queue() ? YES : NO); | |
// Block the current thread until data is written. This is SLOOOOW | |
if (isMain) { | |
NSError *error = nil; | |
[self.managedObjectContext save:&error]; | |
} else { | |
dispatch_sync(dispatch_get_current_queue(), ^{ | |
dispatch_sync(dispatch_get_main_queue(), ^{ | |
NSError *error = nil; | |
[self.managedObjectContext save:&error]; | |
}); | |
}); | |
} | |
// NSManagedObjectIDs are threadsafe | |
return self.objectID; | |
} | |
@end | |
@implementation NSManagedObjectContext (FreezeDry) | |
+ (NSManagedObjectContext*) initContextForCurrentThread | |
{ | |
NSPersistentStoreCoordinator* coordinator; | |
NSManagedObjectContext* moc; | |
NSObject<UIApplicationDelegate>* delegate; | |
// Create new MOC for current thread | |
moc = [[NSManagedObjectContext alloc] init]; | |
delegate = [[UIApplication sharedApplication] delegate]; | |
if (![delegate respondsToSelector:@selector(persistentStoreCoordinator)]) | |
return nil; | |
// Set the default store | |
coordinator = [delegate performSelector:@selector(persistentStoreCoordinator)]; | |
moc.persistentStoreCoordinator = coordinator; | |
return moc; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment