Last active
October 6, 2015 12:28
-
-
Save sumchattering/2993289 to your computer and use it in GitHub Desktop.
Core Data Backgrounding
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
#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