Skip to content
This repository has been archived by the owner on Aug 24, 2019. It is now read-only.

Fix for possible infinite loop for persistent store in bad state #39

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 50 additions & 29 deletions SSDataKit/SSManagedObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -80,35 +93,43 @@ + (BOOL)hasMainContext {
}
#pragma clang diagnostic pop

NSString *kPersistentStoreLock = @"kSSPeristentStoreLock";

+ (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;
@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 {
NSLog(@"[SSDataKit] Failed to add persistent store: %@ %@", error, error.userInfo);
}
} else {
persistentStoreCoordinator = tempPersistentStoreCoordinator;
}
}
}

return persistentStoreCoordinator;
}


+ (NSDictionary *)persistentStoreOptions {
if (!__persistentStoreOptions) {
[self setPersistentStoreOptions:[NSDictionary dictionaryWithObjectsAndKeys:
Expand Down Expand Up @@ -204,7 +225,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];

Expand Down