Skip to content

Instantly share code, notes, and snippets.

@sumchattering
Last active October 6, 2015 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sumchattering/2993289 to your computer and use it in GitHub Desktop.
Save sumchattering/2993289 to your computer and use it in GitHub Desktop.
Core Data Backgrounding
#import "HiveDeviceCoreDataManager.h"
static HiveDeviceCoreDataManager* globalManager = nil;
NSString *const HiveDeviceCoreDataRefetchAllDatabaseData = @"DeviceRefetchAllDatabaseData";
@implementation HiveDeviceCoreDataManager
@synthesize mainContext = _mainContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize initialized = _isInitialized;
///////////////////////////////////////////////////////////////////////////////////////////////////
+ (HiveDeviceCoreDataManager*)globalManager {
return globalManager;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
+ (void)setGlobalManager:(HiveDeviceCoreDataManager*)manager {
if (globalManager!=manager) {
globalManager = manager;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)saveDataInBackgroundWithContext:(void(^)(NSManagedObjectContext *context))saveBlock completion:(void(^)(void))completion
{
if(!self.initialized){
return;
}
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[childContext setParentContext:self.mainContext];
[childContext performBlock:^{
saveBlock(childContext);
if ([childContext hasChanges])
{
NSError* error = nil;
if ([childContext hasChanges] && ![childContext save:&error])
{
HIVETRACKERRORFORMAT(error,@"HiveCoreDataManager Error Saving Child Context %@, %@", error, [error userInfo]);
}
}
dispatch_sync(dispatch_get_main_queue(), ^(void) {
completion();
});
}];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (NSManagedObjectModel *)managedObjectModel
{
if (!_managedObjectModel)
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:SETTINGS(dataModelFileName) withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return _managedObjectModel;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (!_persistentStoreCoordinator)
{
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
[self loadPersistantStore];
}
return _persistentStoreCoordinator;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (NSManagedObjectContext *)mainContext
{
if (!_mainContext)
{
if (self.persistentStoreCoordinator)
{
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
[_mainContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
}
}
return _mainContext;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
-(BOOL) saveContext{
return [self saveContext:self.mainContext];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#pragma mark -
#pragma mark Public Methods
///////////////////////////////////////////////////////////////////////////////////////////////////
-(void)initialize {
//default implementation does nothing.
//To be overridden
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)didInitialize {
//default implementation does nothing
//To be overridden
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)registerForNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification object:nil];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)deleteAllObjectsWithEntityDescription:(NSEntityDescription*)entity inContext:(NSManagedObjectContext*)context{
if(!self.initialized||!context){
return;
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
NSError *error = nil;
NSArray *objectsToDelete = [context executeFetchRequest:request error:&error];
if(objectsToDelete){
for(id objectToDelete in objectsToDelete){
[context deleteObject:objectToDelete];
}
[self saveContext:context];
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)deleteAllObjectsWithEntityDescription:(NSEntityDescription*)entity{
[self deleteAllObjectsWithEntityDescription:entity inContext:self.mainContext];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)saveContext:(NSManagedObjectContext*)context
{
if(!self.initialized||!context){
return NO;
}
@try {
NSError *error = nil;
if ([context hasChanges])
{
BOOL saved = [context save:&error];
if(error||!saved){
HIVETRACKERRORFORMAT(error,@"HiveDeviceCoreDataManager Error Saving Context %@ - %@,%@",context, error, [error userInfo]);
return NO;
}
if([context parentContext]){
[[context parentContext] save:&error];
if(error||!saved){
HIVETRACKERRORFORMAT(error,@"HiveDeviceCoreDataManager Error Saving Parent Context %@ - %@,%@",context, error, [error userInfo]);
return NO;
}
}
}
}
@catch (NSException *exception) {
HIVETRACKEXCEPTIONDESC(exception, @"Exception saving context");
return NO;
}
return YES;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (NSArray*)executeFetchRequest:(NSFetchRequest*)request inContext:(NSManagedObjectContext*)context{
if(!context){
return nil;
}
@try {
NSError* error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
if (!error&&TTIsArrayWithItems(results)){
return results;
} else {
if(error){
HIVETRACKERRORDESC(error,@"Error executing fetch request");
}
return nil;
}
}
@catch (NSException *exception) {
HIVETRACKEXCEPTIONDESC(exception, @"Exception executing fetch request");
return nil;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
- (NSInteger)findCountForFetchRequest:(NSFetchRequest*)request inContext:(NSManagedObjectContext*)context{
if(!context){
return 0;
}
@try {
NSError* error = nil;
NSInteger count = [context countForFetchRequest:request error:&error];
if (!error){
return count;
} else {
HIVETRACKERRORDESC(error,@"Error finding count for fetch request");
return 0;
}
}
@catch (NSException *exception) {
HIVETRACKEXCEPTIONDESC(exception, @"Exception finding count for fetch request");
return 0;
}
}
#pragma mark -
#pragma mark Private
///////////////////////////////////////////////////////////////////////////////////////////////////
-(void) loadPersistantStore{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *storeURL = [[self applicationDocumentsDirectory]
URLByAppendingPathComponent:[NSString stringWithFormat:@"%@_Device.sqlite",SETTINGS(appName)]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
NSError *error = nil;
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
HIVETRACKERRORDESC(error,@"HNCoreDataManager Error Loading PersistantStore");
} else {
[self initialize];
dispatch_sync(dispatch_get_main_queue(), ^{
_isInitialized = YES;
[self didInitialize];
[self registerForNotifications];
[[NSNotificationCenter defaultCenter] postNotificationName:HiveDeviceCoreDataRefetchAllDatabaseData object:self userInfo:nil];
});
}
});
}
#pragma mark -
#pragma mark Notifications
///////////////////////////////////////////////////////////////////////////////////////////////////
-(void)applicationWillTerminate:(NSNotification*)notification{
TTDINFO(@"Saving Context because application will terminate");
[self saveContext];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
-(void)applicationWillResignActive:(NSNotification*)notification{
TTDINFO(@"Saving Context because application will resign active");
[self saveContext];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment