From e6860b0b78a92913ccaa18b46b7d89d168bd8b0c Mon Sep 17 00:00:00 2001 From: Pablo Jablonski Date: Fri, 4 Dec 2015 18:01:20 -0800 Subject: [PATCH 1/4] fixing bug if persistent store in bad state --- SSDataKit/SSManagedObject.m | 64 ++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/SSDataKit/SSManagedObject.m b/SSDataKit/SSManagedObject.m index 5d7a184..1c787b2 100644 --- a/SSDataKit/SSManagedObject.m +++ b/SSDataKit/SSManagedObject.m @@ -82,33 +82,47 @@ + (BOOL)hasMainContext { + (NSPersistentStoreCoordinator *)persistentStoreCoordinator { - static NSPersistentStoreCoordinator *persistentStoreCoordinator = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSManagedObjectModel *model = [self managedObjectModel]; - persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; - - NSURL *url = [self persistentStoreURL]; - NSError *error = nil; - NSDictionary *storeOptions = [self persistentStoreOptions]; - [persistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; - - if (error) { - // Reset the persistent store - BOOL missingError = error.code == NSMigrationMissingSourceModelError || error.code == NSMigrationMissingMappingModelError; - if (__automaticallyResetsPersistentStore && missingError) { - [SSManagedObject removeSQLiteFiles]; - [persistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; - } else { - NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo); - } - } - }); - - return persistentStoreCoordinator; + static NSPersistentStoreCoordinator *persistentStoreCoordinator = nil; + static dispatch_once_t onceToken; + static dispatch_semaphore_t createSemaphore; + dispatch_once(&onceToken, ^{ + createSemaphore = dispatch_semaphore_create(0); + }); + + dispatch_semaphore_signal(createSemaphore); + + if(!persistentStoreCoordinator) { + NSManagedObjectModel *model = [self managedObjectModel]; + NSPersistentStoreCoordinator *tempPersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; + + NSURL *url = [self persistentStoreURL]; + NSError *error = nil; + NSDictionary *storeOptions = [self persistentStoreOptions]; + [tempPersistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; + + if (error) { + // Reset the persistent store + BOOL missingError = error.code == NSMigrationMissingSourceModelError || error.code == NSMigrationMissingMappingModelError; + if (__automaticallyResetsPersistentStore && missingError) { + [SSManagedObject removeSQLiteFiles]; + [tempPersistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; + if(error) { + NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo); + } else { + persistentStoreCoordinator = tempPersistentStoreCoordinator; + } + } else { + NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo); + } + } else { + persistentStoreCoordinator = tempPersistentStoreCoordinator; + } + } + + dispatch_semaphore_wait(createSemaphore, DISPATCH_TIME_FOREVER); + return persistentStoreCoordinator; } - + (NSDictionary *)persistentStoreOptions { if (!__persistentStoreOptions) { [self setPersistentStoreOptions:[NSDictionary dictionaryWithObjectsAndKeys: From dc7662d38ad1afb0a2fc23a00feb564957d40c6e Mon Sep 17 00:00:00 2001 From: Pablo Jablonski Date: Fri, 4 Dec 2015 19:12:44 -0800 Subject: [PATCH 2/4] using synchronized instead --- SSDataKit/SSManagedObject.m | 53 +++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/SSDataKit/SSManagedObject.m b/SSDataKit/SSManagedObject.m index 1c787b2..80aae6e 100644 --- a/SSDataKit/SSManagedObject.m +++ b/SSDataKit/SSManagedObject.m @@ -80,46 +80,41 @@ + (BOOL)hasMainContext { } #pragma clang diagnostic pop +NSString *kPersistentStoreLock = @"kSSPeristentStoreLock"; + (NSPersistentStoreCoordinator *)persistentStoreCoordinator { static NSPersistentStoreCoordinator *persistentStoreCoordinator = nil; - static dispatch_once_t onceToken; - static dispatch_semaphore_t createSemaphore; - dispatch_once(&onceToken, ^{ - createSemaphore = dispatch_semaphore_create(0); - }); - dispatch_semaphore_signal(createSemaphore); - - if(!persistentStoreCoordinator) { - NSManagedObjectModel *model = [self managedObjectModel]; - NSPersistentStoreCoordinator *tempPersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; - - NSURL *url = [self persistentStoreURL]; - NSError *error = nil; - NSDictionary *storeOptions = [self persistentStoreOptions]; - [tempPersistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; - - if (error) { - // Reset the persistent store - BOOL missingError = error.code == NSMigrationMissingSourceModelError || error.code == NSMigrationMissingMappingModelError; - if (__automaticallyResetsPersistentStore && missingError) { - [SSManagedObject removeSQLiteFiles]; - [tempPersistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; - if(error) { - NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo); + @synchronized (kPersistentStoreLock) { + if(!persistentStoreCoordinator) { + NSManagedObjectModel *model = [self managedObjectModel]; + NSPersistentStoreCoordinator *tempPersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; + + NSURL *url = [self persistentStoreURL]; + NSError *error = nil; + NSDictionary *storeOptions = [self persistentStoreOptions]; + [tempPersistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; + + if (error) { + // Reset the persistent store + BOOL missingError = error.code == NSMigrationMissingSourceModelError || error.code == NSMigrationMissingMappingModelError; + if (__automaticallyResetsPersistentStore && missingError) { + [SSManagedObject removeSQLiteFiles]; + [tempPersistentStoreCoordinator addPersistentStoreWithType:[self persistentStoreType] configuration:nil URL:url options:storeOptions error:&error]; + if(error) { + NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo); + } else { + persistentStoreCoordinator = tempPersistentStoreCoordinator; + } } else { - persistentStoreCoordinator = tempPersistentStoreCoordinator; + NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo); } } else { - NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo); + persistentStoreCoordinator = tempPersistentStoreCoordinator; } - } else { - persistentStoreCoordinator = tempPersistentStoreCoordinator; } } - dispatch_semaphore_wait(createSemaphore, DISPATCH_TIME_FOREVER); return persistentStoreCoordinator; } From d2aab381a751e8b0145fa44b18d5720ba3e24483 Mon Sep 17 00:00:00 2001 From: Pablo Jablonski Date: Thu, 31 Mar 2016 14:50:56 -0700 Subject: [PATCH 3/4] calling self to get persistent store coordinator on reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows for subclassing of the persistent store coordinator and is consistent with it’s use in the rest of the file (where self is always used) --- SSDataKit/SSManagedObject.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SSDataKit/SSManagedObject.m b/SSDataKit/SSManagedObject.m index 80aae6e..ac3e858 100644 --- a/SSDataKit/SSManagedObject.m +++ b/SSDataKit/SSManagedObject.m @@ -213,7 +213,7 @@ + (void)resetPersistentStore { // Delete old persistent store NSURL *url = [self persistentStoreURL]; - NSPersistentStoreCoordinator *psc = [SSManagedObject persistentStoreCoordinator]; + NSPersistentStoreCoordinator *psc = [self persistentStoreCoordinator]; if ([psc removePersistentStore:psc.persistentStores.lastObject error:nil]) { [SSManagedObject removeSQLiteFiles]; From 8d1edfeb474278b046df9e11704f4b08e4410724 Mon Sep 17 00:00:00 2001 From: Pablo Jablonski Date: Thu, 28 Apr 2016 11:22:04 -0700 Subject: [PATCH 4/4] not setting the main queue context if persistent store fails --- SSDataKit/SSManagedObject.m | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/SSDataKit/SSManagedObject.m b/SSDataKit/SSManagedObject.m index ac3e858..0e19fb6 100644 --- a/SSDataKit/SSManagedObject.m +++ b/SSDataKit/SSManagedObject.m @@ -26,8 +26,15 @@ @implementation SSManagedObject + (NSManagedObjectContext *)privateQueueContext { if (!__privateQueueContext) { - __privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; - [__privateQueueContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]]; + NSManagedObjectContext *privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; + NSPersistentStoreCoordinator *persistentStoreCoordinator = [self persistentStoreCoordinator]; + if (!persistentStoreCoordinator) { + NSLog(@"Error setting persistent store coordinator!"); + return nil; + } + + [privateQueueContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]]; + __privateQueueContext = privateQueueContext; __contextSaveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil @@ -53,7 +60,13 @@ + (BOOL)hasPrivateQueueContext { + (NSManagedObjectContext *)mainQueueContext { if (!__mainQueueContext) { NSManagedObjectContext *mxct = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; - [mxct setParentContext:[self privateQueueContext]]; + NSManagedObjectContext *parentContext = [self privateQueueContext]; + if(!parentContext) { + NSLog(@"Error generating main parent context!"); + return nil; + } + + [mxct setParentContext:parentContext]; __mainQueueContext = mxct; } return __mainQueueContext; @@ -84,7 +97,6 @@ + (BOOL)hasMainContext { + (NSPersistentStoreCoordinator *)persistentStoreCoordinator { static NSPersistentStoreCoordinator *persistentStoreCoordinator = nil; - @synchronized (kPersistentStoreLock) { if(!persistentStoreCoordinator) { NSManagedObjectModel *model = [self managedObjectModel];