2
0

Handle failure to load store.

This commit is contained in:
Maarten Billemont 2014-09-21 23:11:05 -04:00
parent 58156be793
commit d03b1746e0
5 changed files with 73 additions and 16 deletions

View File

@ -22,5 +22,6 @@
- (MPUserEntity *)activeUserForMainThread; - (MPUserEntity *)activeUserForMainThread;
- (MPUserEntity *)activeUserInContext:(NSManagedObjectContext *)context; - (MPUserEntity *)activeUserInContext:(NSManagedObjectContext *)context;
- (void)setActiveUser:(MPUserEntity *)activeUser; - (void)setActiveUser:(MPUserEntity *)activeUser;
- (void)handleCoordinatorError:(NSError *)error;
@end @end

View File

@ -57,4 +57,8 @@
self.activeUserOID = activeUser.objectID; self.activeUserOID = activeUser.objectID;
} }
- (void)handleCoordinatorError:(NSError *)error {
}
@end @end

View File

@ -27,6 +27,7 @@ typedef NS_ENUM( NSUInteger, MPImportResult ) {
+ (BOOL)managedObjectContextPerformBlockAndWait:(void (^)(NSManagedObjectContext *context))mocBlock; + (BOOL)managedObjectContextPerformBlockAndWait:(void (^)(NSManagedObjectContext *context))mocBlock;
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context; - (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context;
- (void)deleteAndResetStore;
/** @param completion The block to execute after adding the site, executed from the main thread with the new site in the main MOC. */ /** @param completion The block to execute after adding the site, executed from the main thread with the new site in the main MOC. */
- (void)addSiteNamed:(NSString *)siteName completion:(void ( ^ )(MPSiteEntity *site, NSManagedObjectContext *context))completion; - (void)addSiteNamed:(NSString *)siteName completion:(void ( ^ )(MPSiteEntity *site, NSManagedObjectContext *context))completion;

View File

@ -157,12 +157,16 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
err( @"Couldn't create our application support directory: %@", [error fullDescription] ); err( @"Couldn't create our application support directory: %@", [error fullDescription] );
return; return;
} }
[self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:localStoreURL if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self localStoreURL]
options:@{ options:@{
NSMigratePersistentStoresAutomaticallyOption : @YES, NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES,
STORE_OPTIONS STORE_OPTIONS
} error:&error]; } error:&error]) {
err( @"Failed to open store: %@", error );
[self handleCoordinatorError:error];
return;
}
// Create our contexts and observer. // Create our contexts and observer.
self.privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; self.privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
@ -184,16 +188,16 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
}]; }];
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillTerminateNotification object:UIApp [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillTerminateNotification object:UIApp
queue:[NSOperationQueue mainQueue] usingBlock: queue:[NSOperationQueue mainQueue] usingBlock:
^(NSNotification *note) { ^(NSNotification *note) {
[self.mainManagedObjectContext saveToStore]; [self.mainManagedObjectContext saveToStore];
}]; }];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:UIApp [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:UIApp
queue:[NSOperationQueue mainQueue] usingBlock: queue:[NSOperationQueue mainQueue] usingBlock:
^(NSNotification *note) { ^(NSNotification *note) {
[self.mainManagedObjectContext saveToStore]; [self.mainManagedObjectContext saveToStore];
}]; }];
#else #else
[[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillTerminateNotification object:NSApp [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillTerminateNotification object:NSApp
queue:[NSOperationQueue mainQueue] usingBlock: queue:[NSOperationQueue mainQueue] usingBlock:
@ -210,6 +214,33 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
} }
} }
- (void)deleteAndResetStore {
@synchronized (self) {
// Unregister any existing observers and contexts.
if (self.saveObserver)
[[NSNotificationCenter defaultCenter] removeObserver:self.saveObserver];
[self.mainManagedObjectContext performBlockAndWait:^{
[self.mainManagedObjectContext reset];
self.mainManagedObjectContext = nil;
}];
[self.privateManagedObjectContext performBlockAndWait:^{
[self.privateManagedObjectContext reset];
self.privateManagedObjectContext = nil;
}];
NSError *error = nil;
for (NSPersistentStore *store in self.persistentStoreCoordinator.persistentStores) {
if (![self.persistentStoreCoordinator removePersistentStore:store error:&error])
err( @"Couldn't remove persistence store from coordinator: %@", error );
}
self.persistentStoreCoordinator = nil;
if (![[NSFileManager defaultManager] removeItemAtURL:self.localStoreURL error:&error])
err( @"Couldn't remove persistence store at URL %@: %@", self.localStoreURL, error );
[self loadStore];
}
}
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context { - (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context {
NSError *error = nil; NSError *error = nil;

View File

@ -341,6 +341,26 @@
showComposerForVC:viewController]; showComposerForVC:viewController];
} }
- (void)handleCoordinatorError:(NSError *)error {
static dispatch_once_t once = 0;
dispatch_once( &once, ^{
[PearlAlert showAlertWithTitle:@"Failed To Load Sites" message:
@"Master Password was unable to open your sites history.\n"
@"This may be due to corruption. You can either reset Master Password and "
@"recreate your user, or E-Mail us your logs and leave your corrupt store as-is for now."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
if (buttonIndex == [alert cancelButtonIndex])
return;
if (buttonIndex == [alert firstOtherButtonIndex])
[self openFeedbackWithLogs:YES forVC:nil];
if (buttonIndex == [alert firstOtherButtonIndex] + 1)
[self deleteAndResetStore];
} cancelTitle:@"Ignore" otherTitles:@"E-Mail Logs", @"Reset", nil];
} );
}
- (void)showExportForVC:(UIViewController *)viewController { - (void)showExportForVC:(UIViewController *)viewController {
[PearlAlert showAlertWithTitle:@"Exporting Your Sites" [PearlAlert showAlertWithTitle:@"Exporting Your Sites"