diff --git a/External/Mac/Crashlytics.framework/Modules b/External/Mac/Crashlytics.framework/Modules new file mode 120000 index 00000000..5736f318 --- /dev/null +++ b/External/Mac/Crashlytics.framework/Modules @@ -0,0 +1 @@ +Versions/Current/Modules \ No newline at end of file diff --git a/External/Mac/Crashlytics.framework/Versions/A/Crashlytics b/External/Mac/Crashlytics.framework/Versions/A/Crashlytics index 41884f03..65733602 100644 Binary files a/External/Mac/Crashlytics.framework/Versions/A/Crashlytics and b/External/Mac/Crashlytics.framework/Versions/A/Crashlytics differ diff --git a/External/Mac/Crashlytics.framework/Versions/A/Headers/Crashlytics.h b/External/Mac/Crashlytics.framework/Versions/A/Headers/Crashlytics.h index 59addeff..7102c5c1 100644 --- a/External/Mac/Crashlytics.framework/Versions/A/Headers/Crashlytics.h +++ b/External/Mac/Crashlytics.framework/Versions/A/Headers/Crashlytics.h @@ -38,6 +38,7 @@ * **/ OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); +OBJC_EXTERN void CLSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0); /** * @@ -46,6 +47,8 @@ OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); * **/ OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); +OBJC_EXTERN void CLSNSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0); + @protocol CrashlyticsDelegate; diff --git a/External/Mac/Crashlytics.framework/Versions/A/Modules/module.modulemap b/External/Mac/Crashlytics.framework/Versions/A/Modules/module.modulemap new file mode 100644 index 00000000..e552e9ca --- /dev/null +++ b/External/Mac/Crashlytics.framework/Versions/A/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module Crashlytics { + umbrella header "Crashlytics.h" + + export * + module * { export * } +} diff --git a/External/Mac/Crashlytics.framework/Versions/A/Resources/Info.plist b/External/Mac/Crashlytics.framework/Versions/A/Resources/Info.plist index bf21197c..0fa9b7bd 100644 --- a/External/Mac/Crashlytics.framework/Versions/A/Resources/Info.plist +++ b/External/Mac/Crashlytics.framework/Versions/A/Resources/Info.plist @@ -15,13 +15,13 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.1.2 + 2.2.5 CFBundleSupportedPlatforms macosx CFBundleVersion - 9 + 39 DTPlatformName macosx MinimumOSVersion diff --git a/External/Mac/Crashlytics.framework/run b/External/Mac/Crashlytics.framework/run index a43a84fe..b34d4f75 100755 Binary files a/External/Mac/Crashlytics.framework/run and b/External/Mac/Crashlytics.framework/run differ diff --git a/MasterPassword/ObjC/MPAppDelegate_Shared.h b/MasterPassword/ObjC/MPAppDelegate_Shared.h index 24213eba..9827758c 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Shared.h +++ b/MasterPassword/ObjC/MPAppDelegate_Shared.h @@ -16,6 +16,7 @@ @property(strong, nonatomic, readonly) MPKey *key; @property(strong, nonatomic, readonly) NSManagedObjectID *activeUserOID; +@property(strong, nonatomic, readonly) NSPersistentStoreCoordinator *storeCoordinator; + (instancetype)get; diff --git a/MasterPassword/ObjC/MPAppDelegate_Shared.m b/MasterPassword/ObjC/MPAppDelegate_Shared.m index 1d72f074..be65cb0c 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Shared.m +++ b/MasterPassword/ObjC/MPAppDelegate_Shared.m @@ -6,15 +6,16 @@ // Copyright (c) 2011 Lyndir. All rights reserved. // -#import #import "MPAppDelegate_Shared.h" #import "MPAppDelegate_Store.h" #import "MPAppDelegate_Key.h" +#import "NSManagedObjectModel+KCOrderedAccessorFix.h" @interface MPAppDelegate_Shared () @property(strong, nonatomic) MPKey *key; @property(strong, nonatomic) NSManagedObjectID *activeUserOID; +@property(strong, nonatomic) NSPersistentStoreCoordinator *storeCoordinator; @end @@ -31,6 +32,18 @@ #endif } +- (instancetype)init { + + if (!(self = [super init])) + return nil; + + NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil]; + [model kc_generateOrderedSetAccessors]; + self.storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; + + return self; +} + - (MPUserEntity *)activeUserForMainThread { return [self activeUserInContext:[MPAppDelegate_Shared managedObjectContextForMainThreadIfReady]]; diff --git a/MasterPassword/ObjC/MPAppDelegate_Store.m b/MasterPassword/ObjC/MPAppDelegate_Store.m index 65c1aa5c..36172722 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Store.m +++ b/MasterPassword/ObjC/MPAppDelegate_Store.m @@ -7,8 +7,6 @@ // #import "MPAppDelegate_Store.h" -#import "MPGeneratedSiteEntity.h" -#import "NSManagedObjectModel+KCOrderedAccessorFix.h" #if TARGET_OS_IPHONE #define STORE_OPTIONS NSPersistentStoreFileProtectionKey : NSFileProtectionComplete, @@ -27,9 +25,7 @@ typedef NS_ENUM( NSInteger, MPStoreMigrationLevel ) { @implementation MPAppDelegate_Shared(Store) -PearlAssociatedObjectProperty( id, SaveObserver, saveObserver ); - -PearlAssociatedObjectProperty( NSPersistentStoreCoordinator*, PersistentStoreCoordinator, persistentStoreCoordinator ); +PearlAssociatedObjectProperty( NSOperationQueue *, StoreQueue, storeQueue ); PearlAssociatedObjectProperty( NSManagedObjectContext*, PrivateManagedObjectContext, privateManagedObjectContext ); @@ -58,7 +54,8 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); [mainManagedObjectContext performBlock:^{ @try { mocBlock( mainManagedObjectContext ); - } @catch (NSException *exception) { + } + @catch (NSException *exception) { err( @"While performing managed block:\n%@", [exception fullDescription] ); } }]; @@ -148,14 +145,22 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); - (void)loadStore { - @synchronized (self) { + static dispatch_once_t once = 0; + dispatch_once( &once, ^{ + (self.storeQueue = [NSOperationQueue new]).maxConcurrentOperationCount = 1; + } ); + + // Do nothing if already fully set up, otherwise (re-)load the store. + if (self.storeCoordinator && self.mainManagedObjectContext && self.privateManagedObjectContext) + return; + + [self.storeQueue addOperationWithBlock:^{ // Do nothing if already fully set up, otherwise (re-)load the store. - if (self.persistentStoreCoordinator && self.saveObserver && self.mainManagedObjectContext && self.privateManagedObjectContext) + if (self.storeCoordinator && self.mainManagedObjectContext && self.privateManagedObjectContext) return; // Unregister any existing observers and contexts. - if (self.saveObserver) - [[NSNotificationCenter defaultCenter] removeObserver:self.saveObserver]; + PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext ); [self.mainManagedObjectContext performBlockAndWait:^{ [self.mainManagedObjectContext reset]; self.mainManagedObjectContext = nil; @@ -172,13 +177,31 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); // Check if migration is necessary. [self migrateStore]; - // Create a new store coordinator. - if (!self.persistentStoreCoordinator) { - NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil]; - [model kc_generateOrderedSetAccessors]; - self.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; - } + // Install managed object contexts and observers. + self.privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; + [self.privateManagedObjectContext performBlockAndWait:^{ + self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; + self.privateManagedObjectContext.persistentStoreCoordinator = self.storeCoordinator; + }]; + self.mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; + self.mainManagedObjectContext.parentContext = self.privateManagedObjectContext; + + // When privateManagedObjectContext is saved, import the changes into mainManagedObjectContext. + PearlAddNotificationObserverTo( self.mainManagedObjectContext, NSManagedObjectContextDidSaveNotification, + self.privateManagedObjectContext, nil, ^(NSManagedObjectContext *mainManagedObjectContext, NSNotification *note) { + [mainManagedObjectContext performBlock:^{ + @try { + [mainManagedObjectContext mergeChangesFromContextDidSaveNotification:note]; + } + @catch (NSException *exception) { + err( @"While merging changes:\n%@",[exception fullDescription] ); + } + }]; + } ); + + + // Create a new store coordinator. NSError *error = nil; NSURL *localStoreURL = [self localStoreURL]; if (![[NSFileManager defaultManager] createDirectoryAtURL:[localStoreURL URLByDeletingLastPathComponent] @@ -186,12 +209,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); err( @"Couldn't create our application support directory: %@", [error fullDescription] ); return; } - if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self localStoreURL] - options:@{ - NSMigratePersistentStoresAutomaticallyOption : @YES, - NSInferMappingModelAutomaticallyOption : @YES, - STORE_OPTIONS - } error:&error]) { + if (![self.storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self localStoreURL] + options:@{ + NSMigratePersistentStoresAutomaticallyOption : @YES, + NSInferMappingModelAutomaticallyOption : @YES, + STORE_OPTIONS + } error:&error]) { err( @"Failed to open store: %@", [error fullDescription] ); self.storeCorrupted = @YES; [self handleCoordinatorError:error]; @@ -199,30 +222,6 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); } self.storeCorrupted = @NO; - // Create our contexts and observer. - self.privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; - [self.privateManagedObjectContext performBlockAndWait:^{ - self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; - self.privateManagedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator; - }]; - - self.mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; - self.mainManagedObjectContext.parentContext = self.privateManagedObjectContext; - - self.saveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification - object:self.privateManagedObjectContext queue:nil usingBlock: - ^(NSNotification *note) { - // When privateManagedObjectContext is saved, import the changes into mainManagedObjectContext. - [self.mainManagedObjectContext performBlock:^{ - @try { - [self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:note]; - } - @catch (NSException *exception) { - err( @"While merging changes:\n%@", [exception fullDescription] ); - } - }]; - }]; - #if TARGET_OS_IPHONE PearlAddNotificationObserver( UIApplicationWillTerminateNotification, UIApp, [NSOperationQueue mainQueue], ^(MPAppDelegate_Shared *self, NSNotification *note) { @@ -244,15 +243,14 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); [MPAppDelegate_Shared managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) { [self findAndFixInconsistenciesSaveInContext:context]; }]; - } + }]; } - (void)deleteAndResetStore { @synchronized (self) { // Unregister any existing observers and contexts. - if (self.saveObserver) - [[NSNotificationCenter defaultCenter] removeObserver:self.saveObserver]; + PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext ); [self.mainManagedObjectContext performBlockAndWait:^{ [self.mainManagedObjectContext reset]; self.mainManagedObjectContext = nil; @@ -262,11 +260,10 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); self.privateManagedObjectContext = nil; }]; NSError *error = nil; - for (NSPersistentStore *store in self.persistentStoreCoordinator.persistentStores) { - if (![self.persistentStoreCoordinator removePersistentStore:store error:&error]) + for (NSPersistentStore *store in self.storeCoordinator.persistentStores) { + if (![self.storeCoordinator removePersistentStore:store error:&error]) err( @"Couldn't remove persistence store from coordinator: %@", [error fullDescription] ); } - self.persistentStoreCoordinator = nil; if (![[NSFileManager defaultManager] removeItemAtURL:self.localStoreURL error:&error]) err( @"Couldn't remove persistence store at URL %@: %@", self.localStoreURL, [error fullDescription] ); diff --git a/MasterPassword/ObjC/Mac/MPMacAppDelegate.m b/MasterPassword/ObjC/Mac/MPMacAppDelegate.m index 0e2294e6..97c4e95e 100644 --- a/MasterPassword/ObjC/Mac/MPMacAppDelegate.m +++ b/MasterPassword/ObjC/Mac/MPMacAppDelegate.m @@ -80,18 +80,30 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven self.statusView.target = self; self.statusView.action = @selector( showMenu ); - [[NSNotificationCenter defaultCenter] addObserverForName:NSPersistentStoreCoordinatorStoresDidChangeNotification object:nil - queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - [self updateUsers]; - }]; - [[NSNotificationCenter defaultCenter] addObserverForName:MPCheckConfigNotification object:nil - queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - NSString *key = note.object; - if (!key || [key isEqualToString:NSStringFromSelector( @selector( hidePasswords ) )]) - self.hidePasswordsItem.state = [[MPConfig get].hidePasswords boolValue]? NSOnState: NSOffState; - if (!key || [key isEqualToString:NSStringFromSelector( @selector( rememberLogin ) )]) - self.rememberPasswordItem.state = [[MPConfig get].rememberLogin boolValue]? NSOnState: NSOffState; - }]; + PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, self.storeCoordinator, nil, + ^(id self, NSNotification *note) { + PearlMainQueue( ^{ + [self updateUsers]; + } ); + } ); + PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, self.storeCoordinator, nil, + ^(id self, NSNotification *note) { + PearlMainQueue( ^{ + [self updateUsers]; + } ); + } ); + PearlAddNotificationObserver( MPCheckConfigNotification, nil, nil, + ^(MPMacAppDelegate *self, NSNotification *note) { + PearlMainQueue( ^{ + NSString *key = note.object; + if (!key || [key isEqualToString:NSStringFromSelector( @ + selector( hidePasswords ) )]) + self.hidePasswordsItem.state = [[MPConfig get].hidePasswords boolValue]? NSOnState: NSOffState; + if (!key || [key isEqualToString:NSStringFromSelector( @ + selector( rememberLogin ) )]) + self.rememberPasswordItem.state = [[MPConfig get].rememberLogin boolValue]? NSOnState: NSOffState; + } ); + } ); [self updateUsers]; // Global hotkey. @@ -172,12 +184,9 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven NSArray *jobs = (__bridge_transfer NSArray *)SMCopyAllJobDictionaries( kSMDomainUserLaunchd ); for (NSDictionary *job in jobs) - if ([LOGIN_HELPER_BUNDLE_ID isEqualToString:job[@"Label"]]) { - dbg( @"loginItemEnabled: %@", @([job[@"OnDemand"] boolValue]) ); + if ([LOGIN_HELPER_BUNDLE_ID isEqualToString:job[@"Label"]]) return [job[@"OnDemand"] boolValue]; - } - dbg( @"loginItemEnabled: not found" ); return NO; } @@ -454,12 +463,14 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords]; [[[NSFileCoordinator alloc] initWithFilePresenter:nil] coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) { - NSError *writeError = nil; - if (![exportedSites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError]) - PearlMainQueue( ^{ - [[NSAlert alertWithError:writeError] runModal]; - } ); - }]; + NSError *writeError = nil; + if (![exportedSites writeToURL:newURL atomically:NO + encoding:NSUTF8StringEncoding + error:&writeError]) + PearlMainQueue( ^{ + [[NSAlert alertWithError:writeError] runModal]; + } ); + }]; if (coordinateError) PearlMainQueue( ^{ [[NSAlert alertWithError:coordinateError] runModal]; diff --git a/MasterPassword/ObjC/Mac/MPNoStateButton.h b/MasterPassword/ObjC/Mac/MPNoStateButton.h new file mode 100644 index 00000000..d347e5d2 --- /dev/null +++ b/MasterPassword/ObjC/Mac/MPNoStateButton.h @@ -0,0 +1,23 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPNoStateButton.h +// MPNoStateButton +// +// Created by lhunath on 14-10-27. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import + + +@interface MPNoStateButtonCell : NSButtonCell +@end diff --git a/MasterPassword/ObjC/Mac/MPNoStateButton.m b/MasterPassword/ObjC/Mac/MPNoStateButton.m new file mode 100644 index 00000000..7c06e6a2 --- /dev/null +++ b/MasterPassword/ObjC/Mac/MPNoStateButton.m @@ -0,0 +1,31 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPNoStateButton.h +// MPNoStateButton +// +// Created by lhunath on 14-10-27. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import "MPNoStateButton.h" + + +@implementation MPNoStateButtonCell { + +} + +- (void)setState:(NSInteger)state { + + [super setState:NSOnState]; +} + +@end diff --git a/MasterPassword/ObjC/Mac/MPPasswordWindowController.h b/MasterPassword/ObjC/Mac/MPPasswordWindowController.h index 2bc790f6..ee4fdcbd 100644 --- a/MasterPassword/ObjC/Mac/MPPasswordWindowController.h +++ b/MasterPassword/ObjC/Mac/MPPasswordWindowController.h @@ -29,6 +29,7 @@ @property(nonatomic) BOOL alternatePressed; @property(nonatomic) BOOL locked; @property(nonatomic) BOOL newUser; +@property(nonatomic) BOOL alwaysYes; @property(nonatomic, weak) IBOutlet NSArrayController *sitesController; @property(nonatomic, weak) IBOutlet NSImageView *blurView; diff --git a/MasterPassword/ObjC/Mac/MPPasswordWindowController.m b/MasterPassword/ObjC/Mac/MPPasswordWindowController.m index 6c18217e..04340736 100644 --- a/MasterPassword/ObjC/Mac/MPPasswordWindowController.m +++ b/MasterPassword/ObjC/Mac/MPPasswordWindowController.m @@ -116,7 +116,6 @@ - (void)doCommandBySelector:(SEL)commandSelector { - dbg( @"doCommandBySelector: %@", NSStringFromSelector( commandSelector ) ); [self handleCommand:commandSelector]; } @@ -124,19 +123,18 @@ - (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector { - dbg( @"@control:%@ textView:%@ doCommandBySelector:%@", control, fieldEditor, NSStringFromSelector( commandSelector ) ); if (control == self.siteField) { if ([NSStringFromSelector( commandSelector ) rangeOfString:@"delete"].location == 0) { _skipTextChange = YES; - return NO; + dbg_return_tr( NO, @, control, NSStringFromSelector( commandSelector ) ); } } if (control == self.securePasswordField || control == self.revealPasswordField) { if (commandSelector == @selector( insertNewline: )) - return NO; + dbg_return_tr( NO, @, control, NSStringFromSelector( commandSelector ) ); } - return [self handleCommand:commandSelector]; + dbg_return_tr( [self handleCommand:commandSelector], @, control, NSStringFromSelector( commandSelector ) ); } - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor { @@ -312,6 +310,14 @@ return [self.siteField.stringValue stringByReplacingCharactersInRange:self.siteField.currentEditor.selectedRange withString:@""]?: @""; } +- (BOOL)alwaysYes { + + return YES; +} + +- (void)setAlwaysYes:(BOOL)alwaysYes { +} + - (void)insertObject:(MPSiteModel *)model inSitesAtIndex:(NSUInteger)index { [self.sites insertObject:model atIndex:index]; diff --git a/MasterPassword/ObjC/Mac/MPPasswordWindowController.xib b/MasterPassword/ObjC/Mac/MPPasswordWindowController.xib index 47793877..5fb22575 100644 --- a/MasterPassword/ObjC/Mac/MPPasswordWindowController.xib +++ b/MasterPassword/ObjC/Mac/MPPasswordWindowController.xib @@ -1,14 +1,13 @@ - + - - + + - @@ -17,33 +16,42 @@ + - + - + - + - + - + + + + + + + + + @@ -51,13 +59,13 @@ - + - + NSAllRomanInputSourcesLocaleIdentifier @@ -86,13 +94,13 @@ - + - + NSAllRomanInputSourcesLocaleIdentifier @@ -123,11 +131,11 @@ - - + @@ -296,13 +302,13 @@ - + - + @@ -338,10 +344,10 @@ - - + + - + @@ -654,13 +660,13 @@ - + - + @@ -681,14 +687,14 @@ - - + + - + @@ -709,14 +715,14 @@ - - + + - + @@ -746,14 +752,14 @@ - - + + - + @@ -788,13 +794,13 @@ - + - + @@ -810,7 +816,7 @@ - + @@ -822,7 +828,7 @@ - + @@ -845,7 +851,7 @@ - + @@ -858,7 +864,7 @@ - + @@ -867,6 +873,7 @@ + diff --git a/MasterPassword/ObjC/Mac/MPSiteModel.m b/MasterPassword/ObjC/Mac/MPSiteModel.m index a6299611..c7dd6ed7 100644 --- a/MasterPassword/ObjC/Mac/MPSiteModel.m +++ b/MasterPassword/ObjC/Mac/MPSiteModel.m @@ -48,7 +48,6 @@ self.algorithm = entity.algorithm; self.siteName = entity.name; self.lastUsed = entity.lastUsed; - self.loginName = entity.loginName; self.type = entity.type; self.typeName = entity.typeName; self.uses = entity.uses_; @@ -127,6 +126,11 @@ self.contentDisplay = displayResult; } ); }]; + [entity resolveLoginUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) { + PearlMainQueue( ^{ + self.loginName = result; + } ); + }]; } @end diff --git a/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj b/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj index 27f10711..035f2cd7 100644 --- a/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */; }; 93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */; }; 93D394C4254EEB45FB335AFB /* MPSitesTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39423D7BF4FD31FE6D27C /* MPSitesTableView.m */; }; + 93D395E4830290EBB6E71F34 /* MPNoStateButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39538C4CEFF46DF379254 /* MPNoStateButton.m */; }; 93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; }; 93D3970BCF85F7902E611168 /* PearlProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DB3A8ADED08C39A6228 /* PearlProfiler.m */; }; 93D39784E725A34D1EE3FB3B /* MPInitialWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D3CB30874147D9A9E1B /* MPInitialWindowController.m */; }; @@ -55,13 +56,14 @@ DA3B8456190FC89700246EEA /* MPFixable.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B8454190FC89700246EEA /* MPFixable.m */; }; DA3BCFCD19BD09E0006B2681 /* SourceCodePro-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA3BCFCC19BD09E0006B2681 /* SourceCodePro-Regular.otf */; }; DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; }; + DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */; }; + DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */; }; DA5E5C9417248AA1003798D8 /* libscryptenc-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5E5C8717248AA1003798D8 /* libscryptenc-osx.a */; }; DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C981724A667003798D8 /* MPAlgorithm.m */; }; DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9A1724A667003798D8 /* MPAlgorithmV0.m */; }; DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9C1724A667003798D8 /* MPAlgorithmV1.m */; }; DA5E5CF91724A667003798D8 /* MPAppDelegate_Key.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9E1724A667003798D8 /* MPAppDelegate_Key.m */; }; DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA01724A667003798D8 /* MPAppDelegate_Shared.m */; }; - DA5E5CFB1724A667003798D8 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA21724A667003798D8 /* MPAppDelegate_Store.m */; }; DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CA41724A667003798D8 /* MPConfig.m */; }; DA5E5D001724A667003798D8 /* MPEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CAC1724A667003798D8 /* MPEntities.m */; }; DA5E5D011724A667003798D8 /* MPKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CAE1724A667003798D8 /* MPKey.m */; }; @@ -238,11 +240,13 @@ /* Begin PBXFileReference section */ 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = ""; }; 93D39240B5143E01F0B75E96 /* MPSiteModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteModel.h; sourceTree = ""; }; + 93D392A4F3DE0BD758B9B056 /* MPNoStateButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNoStateButton.h; sourceTree = ""; }; 93D392C3918763B3B72CF366 /* MPPasswordWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindowController.h; sourceTree = ""; }; 93D39368EF3CBFEF2AFCA15A /* MPInitialWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInitialWindowController.h; sourceTree = ""; }; 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = ""; }; 93D39423D7BF4FD31FE6D27C /* MPSitesTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesTableView.m; sourceTree = ""; }; 93D394EEFF5BF555A55AF361 /* PearlProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PearlProfiler.h; path = ../../../External/Pearl/Pearl/PearlProfiler.h; sourceTree = ""; }; + 93D39538C4CEFF46DF379254 /* MPNoStateButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNoStateButton.m; sourceTree = ""; }; 93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = ""; }; 93D3977484534E99F9BA579D /* MPPasswordWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindow.h; sourceTree = ""; }; 93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordWindowController.m; sourceTree = ""; }; @@ -301,6 +305,10 @@ DA3B8454190FC89700246EEA /* MPFixable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPFixable.m; sourceTree = ""; }; DA3B8455190FC89700246EEA /* MPFixable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPFixable.h; sourceTree = ""; }; DA3BCFCC19BD09E0006B2681 /* SourceCodePro-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-Regular.otf"; sourceTree = ""; }; + DA5180C619FF2F9200A587E9 /* MPAlgorithmV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV2.h; sourceTree = ""; }; + DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV2.m; sourceTree = ""; }; + DA5180CC19FF307E00A587E9 /* MPAppDelegate_Store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_Store.h; sourceTree = ""; }; + DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Store.m; sourceTree = ""; }; DA5BFA44147E415C00F98B1E /* Master Password.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Master Password.app"; sourceTree = BUILT_PRODUCTS_DIR; }; DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -316,8 +324,6 @@ DA5E5C9E1724A667003798D8 /* MPAppDelegate_Key.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Key.m; sourceTree = ""; }; DA5E5C9F1724A667003798D8 /* MPAppDelegate_Shared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_Shared.h; sourceTree = ""; }; DA5E5CA01724A667003798D8 /* MPAppDelegate_Shared.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Shared.m; sourceTree = ""; }; - DA5E5CA11724A667003798D8 /* MPAppDelegate_Store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_Store.h; sourceTree = ""; }; - DA5E5CA21724A667003798D8 /* MPAppDelegate_Store.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Store.m; sourceTree = ""; }; DA5E5CA31724A667003798D8 /* MPConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPConfig.h; sourceTree = ""; }; DA5E5CA41724A667003798D8 /* MPConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPConfig.m; sourceTree = ""; }; DA5E5CAB1724A667003798D8 /* MPEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEntities.h; sourceTree = ""; }; @@ -1016,39 +1022,41 @@ DA5E5C961724A667003798D8 /* ObjC */ = { isa = PBXGroup; children = ( - DA32CFE319CF1C71004F3F0E /* MPUserEntity.h */, - DA32CFE419CF1C71004F3F0E /* MPUserEntity.m */, - DA32CFE019CF1C71004F3F0E /* MPSiteQuestionEntity.h */, - DA32CFE119CF1C71004F3F0E /* MPSiteQuestionEntity.m */, - DA32CFDD19CF1C70004F3F0E /* MPSiteEntity.h */, - DA32CFDE19CF1C70004F3F0E /* MPSiteEntity.m */, - DA32CFDA19CF1C70004F3F0E /* MPStoredSiteEntity.h */, - DA32CFDB19CF1C70004F3F0E /* MPStoredSiteEntity.m */, - DA32CFD719CF1C70004F3F0E /* MPGeneratedSiteEntity.h */, - DA32CFD819CF1C70004F3F0E /* MPGeneratedSiteEntity.m */, - DA3B8454190FC89700246EEA /* MPFixable.m */, - DA3B8455190FC89700246EEA /* MPFixable.h */, DA5E5CB21724A667003798D8 /* Mac */, + DA29992619C6A89900AF7DF1 /* MasterPassword.xcdatamodeld */, DA5E5C971724A667003798D8 /* MPAlgorithm.h */, DA5E5C981724A667003798D8 /* MPAlgorithm.m */, DA5E5C991724A667003798D8 /* MPAlgorithmV0.h */, DA5E5C9A1724A667003798D8 /* MPAlgorithmV0.m */, DA5E5C9B1724A667003798D8 /* MPAlgorithmV1.h */, DA5E5C9C1724A667003798D8 /* MPAlgorithmV1.m */, + DA5180C619FF2F9200A587E9 /* MPAlgorithmV2.h */, + DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */, DA5E5C9D1724A667003798D8 /* MPAppDelegate_Key.h */, DA5E5C9E1724A667003798D8 /* MPAppDelegate_Key.m */, DA5E5C9F1724A667003798D8 /* MPAppDelegate_Shared.h */, DA5E5CA01724A667003798D8 /* MPAppDelegate_Shared.m */, - DA5E5CA11724A667003798D8 /* MPAppDelegate_Store.h */, - DA5E5CA21724A667003798D8 /* MPAppDelegate_Store.m */, + DA5180CC19FF307E00A587E9 /* MPAppDelegate_Store.h */, + DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */, DA5E5CA31724A667003798D8 /* MPConfig.h */, DA5E5CA41724A667003798D8 /* MPConfig.m */, DA5E5CAB1724A667003798D8 /* MPEntities.h */, DA5E5CAC1724A667003798D8 /* MPEntities.m */, + DA3B8455190FC89700246EEA /* MPFixable.h */, + DA3B8454190FC89700246EEA /* MPFixable.m */, + DA32CFD719CF1C70004F3F0E /* MPGeneratedSiteEntity.h */, + DA32CFD819CF1C70004F3F0E /* MPGeneratedSiteEntity.m */, DA5E5CAD1724A667003798D8 /* MPKey.h */, DA5E5CAE1724A667003798D8 /* MPKey.m */, + DA32CFDD19CF1C70004F3F0E /* MPSiteEntity.h */, + DA32CFDE19CF1C70004F3F0E /* MPSiteEntity.m */, + DA32CFE019CF1C71004F3F0E /* MPSiteQuestionEntity.h */, + DA32CFE119CF1C71004F3F0E /* MPSiteQuestionEntity.m */, + DA32CFDA19CF1C70004F3F0E /* MPStoredSiteEntity.h */, + DA32CFDB19CF1C70004F3F0E /* MPStoredSiteEntity.m */, DA5E5CAF1724A667003798D8 /* MPTypes.h */, - DA29992619C6A89900AF7DF1 /* MasterPassword.xcdatamodeld */, + DA32CFE319CF1C71004F3F0E /* MPUserEntity.h */, + DA32CFE419CF1C71004F3F0E /* MPUserEntity.m */, ); name = ObjC; path = ..; @@ -1080,6 +1088,8 @@ 93D39368EF3CBFEF2AFCA15A /* MPInitialWindowController.h */, 93D39423D7BF4FD31FE6D27C /* MPSitesTableView.m */, 93D39AC6360DDC16AEAA4119 /* MPSitesTableView.h */, + 93D39538C4CEFF46DF379254 /* MPNoStateButton.m */, + 93D392A4F3DE0BD758B9B056 /* MPNoStateButton.h */, ); path = Mac; sourceTree = ""; @@ -2182,8 +2192,8 @@ DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */, DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */, DA5E5CF91724A667003798D8 /* MPAppDelegate_Key.m in Sources */, + DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */, DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */, - DA5E5CFB1724A667003798D8 /* MPAppDelegate_Store.m in Sources */, DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */, DA29992C19C6A89900AF7DF1 /* MasterPassword.xcdatamodeld in Sources */, DA3B8456190FC89700246EEA /* MPFixable.m in Sources */, @@ -2194,12 +2204,14 @@ DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */, DA5E5D0C1724A667003798D8 /* main.m in Sources */, 93D39C5789EFA607CF788082 /* MPSiteModel.m in Sources */, + DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */, 93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */, DA32CFD919CF1C70004F3F0E /* MPGeneratedSiteEntity.m in Sources */, 93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */, 93D39784E725A34D1EE3FB3B /* MPInitialWindowController.m in Sources */, DA32CFDF19CF1C70004F3F0E /* MPSiteEntity.m in Sources */, 93D394C4254EEB45FB335AFB /* MPSitesTableView.m in Sources */, + 93D395E4830290EBB6E71F34 /* MPNoStateButton.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2488,7 +2500,7 @@ DA5BFA6E147E415C00F98B1E /* Debug-Mac */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; @@ -2512,7 +2524,7 @@ DA5BFA6F147E415C00F98B1E /* AdHoc-Mac */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements; CODE_SIGN_IDENTITY = "Developer ID Application"; @@ -2612,7 +2624,7 @@ DA95D60A14DF3F3B008D1B94 /* AppStore-Mac */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements; CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; diff --git a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m index 9b33266c..fee25fcd 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m +++ b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m @@ -316,25 +316,33 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { self.passwordSelectionContainer.alpha = 1; }]; } ); - PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue], + PearlAddNotificationObserver( MPSignedOutNotification, nil, nil, ^(MPPasswordsViewController *self, NSNotification *note) { - _fetchedResultsController = nil; - self.passwordsSearchBar.text = nil; - [self.passwordCollectionView reloadData]; + PearlMainQueue( ^{ + _fetchedResultsController = nil; + self.passwordsSearchBar.text = nil; + [self.passwordCollectionView reloadData]; + } ); } ); - PearlAddNotificationObserver( MPCheckConfigNotification, nil, [NSOperationQueue mainQueue], + PearlAddNotificationObserver( MPCheckConfigNotification, nil, nil, ^(MPPasswordsViewController *self, NSNotification *note) { - [self updateConfigKey:note.object]; + PearlMainQueue( ^{ + [self updateConfigKey:note.object]; + } ); } ); PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, nil, nil, ^(MPPasswordsViewController *self, NSNotification *note) { self->_fetchedResultsController = nil; - [self.passwordCollectionView reloadData]; + PearlMainQueue( ^{ + [self.passwordCollectionView reloadData]; + } ); } ); PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, nil, nil, ^(MPPasswordsViewController *self, NSNotification *note) { - [self updatePasswords]; - [self registerObservers]; + PearlMainQueue( ^{ + [self updatePasswords]; + [self registerObservers]; + } ); } ); NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady]; diff --git a/MasterPassword/ObjC/iOS/MPUsersViewController.m b/MasterPassword/ObjC/iOS/MPUsersViewController.m index c6cf6069..c64d76eb 100644 --- a/MasterPassword/ObjC/iOS/MPUsersViewController.m +++ b/MasterPassword/ObjC/iOS/MPUsersViewController.m @@ -666,7 +666,7 @@ referenceSizeForFooterInSection:(NSInteger)section { [self.storeLoadingActivity startAnimating]; if (mainContext) - PearlAddNotificationObserver( NSManagedObjectContextObjectsDidChangeNotification, mainContext, [NSOperationQueue mainQueue], + PearlAddNotificationObserver( NSManagedObjectContextObjectsDidChangeNotification, mainContext, nil, ^(MPUsersViewController *self, NSNotification *note) { NSSet *insertedObjects = note.userInfo[NSInsertedObjectsKey]; NSSet *deletedObjects = note.userInfo[NSDeletedObjectsKey]; @@ -676,11 +676,11 @@ referenceSizeForFooterInSection:(NSInteger)section { }]] count]) [self reloadUsers]; } ); - PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, nil, [NSOperationQueue mainQueue], + PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, [MPiOSAppDelegate get].storeCoordinator, nil, ^(MPUsersViewController *self, NSNotification *note) { self.userIDs = nil; } ); - PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, nil, [NSOperationQueue mainQueue], + PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, [MPiOSAppDelegate get].storeCoordinator, nil, ^(MPUsersViewController *self, NSNotification *note) { [self registerObservers]; [self reloadUsers];