2
0

Improve notification registration and cleanup + fix removal of site questions.

This commit is contained in:
Maarten Billemont 2014-09-27 01:27:05 -04:00
parent 44f91e0618
commit 5db083bf7c
14 changed files with 226 additions and 339 deletions

2
External/Pearl vendored

@ -1 +1 @@
Subproject commit fb7562df9c3a59e8ac21e492b8eac0abcf5aa46e
Subproject commit c4620deda26475ae4320d9af5b2df4ff96c9093e

View File

@ -192,22 +192,19 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
}];
#if TARGET_OS_IPHONE
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillTerminateNotification object:UIApp
queue:[NSOperationQueue mainQueue] usingBlock:
^(NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:UIApp
queue:[NSOperationQueue mainQueue] usingBlock:
^(NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
}];
PearlAddNotificationObserver( UIApplicationWillTerminateNotification, UIApp, [NSOperationQueue mainQueue],
^(MPAppDelegate_Shared *self, NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
} );
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, UIApp, [NSOperationQueue mainQueue],
^(MPAppDelegate_Shared *self, NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
} );
#else
[[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillTerminateNotification object:NSApp
queue:[NSOperationQueue mainQueue] usingBlock:
^(NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
}];
PearlAddNotificationObserver( NSApplicationWillTerminateNotification, NSApp, [NSOperationQueue mainQueue],
^(MPAppDelegate_Shared *self, NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
} );
#endif
// Perform a data sanity check on the newly loaded store to find and fix any issues.
@ -528,7 +525,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
return MPImportResultMalformedInput;
}
NSTextCheckingResult *headerSites = [[headerPattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
if ([headerName isEqualToString:@"User Name"]) {

View File

@ -13,6 +13,6 @@
@interface MPStoredSiteEntity : MPSiteEntity
@property (nonatomic, retain) id contentObject;
@property (nonatomic, retain) NSData *contentObject;
@end

View File

@ -14,6 +14,7 @@
#import "MPPasswordsViewController.h"
#import "MPCoachmarkViewController.h"
#import "MPSiteQuestionEntity.h"
#import "MPOverlayViewController.h"
@interface MPAnswersViewController()
@ -35,6 +36,25 @@
self.view.backgroundColor = [UIColor clearColor];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue], ^(NSNotification *note) {
if (![note.userInfo[@"animated"] boolValue])
[UIView setAnimationsEnabled:NO];
[[MPOverlaySegue dismissViewController:self] perform];
[UIView setAnimationsEnabled:YES];
} );
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
PearlRemoveNotificationObservers();
}
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
@ -147,7 +167,10 @@
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *site_ = [self siteInContext:context];
[site_ removeQuestions:site_.questions];
NSOrderedSet *questions = [site_.questions copy];
for (MPSiteQuestionEntity *question in questions)
[context deleteObject:question];
[site_ removeQuestions:questions];
[context saveToStore];
[self setMultiple:NO animated:YES];
}];

View File

@ -22,9 +22,7 @@
#import "MPEmergencyViewController.h"
#import "MPPasswordsSegue.h"
@implementation MPCombinedViewController {
NSArray *_notificationObservers;
}
@implementation MPCombinedViewController
#pragma mark - Life
@ -47,14 +45,22 @@
[super viewDidAppear:animated];
[self registerObservers];
Weakify( self );
PearlAddNotificationObserver( MPSignedInNotification, nil, [NSOperationQueue mainQueue], ^(NSNotification *note) {
Strongify( self );
[self setMode:MPCombinedModePasswordSelection];
} );
PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue], ^(NSNotification *note) {
Strongify( self );
[self setMode:MPCombinedModeUserSelection animated:[note.userInfo[@"animated"] boolValue]];
} );
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self removeObservers];
PearlRemoveNotificationObservers();
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
@ -142,35 +148,4 @@
#pragma mark - Private
- (void)registerObservers {
if ([_notificationObservers count])
return;
Weakify( self );
_notificationObservers = @[
[[NSNotificationCenter defaultCenter]
addObserverForName:MPSignedInNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
[self setMode:MPCombinedModePasswordSelection];
}],
[[NSNotificationCenter defaultCenter]
addObserverForName:MPSignedOutNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
[self setMode:MPCombinedModeUserSelection animated:[note.userInfo[@"animated"] boolValue]];
}],
];
}
- (void)removeObservers {
for (id observer in _notificationObservers)
[[NSNotificationCenter defaultCenter] removeObserver:observer];
_notificationObservers = nil;
}
@end

View File

@ -1,12 +1,12 @@
/**
* 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 <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
* 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 <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//
// MPCombinedViewController.h
@ -23,7 +23,6 @@
MPKey *_key;
NSOperationQueue *_emergencyKeyQueue;
NSOperationQueue *_emergencyPasswordQueue;
NSArray *_notificationObservers;
}
- (void)viewDidLoad {
@ -42,14 +41,17 @@
[super viewWillAppear:animated];
[self reset];
[self registerObservers];
PearlAddNotificationObserver( UIApplicationWillResignActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPEmergencyViewController *self, NSNotification *note) {
[self performSegueWithIdentifier:@"unwind-popover" sender:self];
} );
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self removeObservers];
PearlRemoveNotificationObservers();
[self reset];
}
@ -154,7 +156,7 @@
case 5:
return MPSiteTypeGeneratedPIN;
default:
Throw(@"Unsupported type index: %ld", (long)self.typeControl.selectedSegmentIndex);
Throw( @"Unsupported type index: %ld", (long)self.typeControl.selectedSegmentIndex );
}
}
@ -168,28 +170,4 @@
[self updateKey];
}
- (void)registerObservers {
if ([_notificationObservers count])
return;
Weakify(self);
_notificationObservers = @[
[[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationWillResignActiveNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify(self);
[self performSegueWithIdentifier:@"unwind-popover" sender:self];
}],
];
}
- (void)removeObservers {
for (id observer in _notificationObservers)
[[NSNotificationCenter defaultCenter] removeObserver:observer];
_notificationObservers = nil;
}
@end

View File

@ -1,12 +1,12 @@
/**
* 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 <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
* 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 <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//
// MPLogsViewController.h
@ -27,18 +27,17 @@
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
[[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:
^(NSNotification *note) {
self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0;
}];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PearlAddNotificationObserver( NSUserDefaultsDidChangeNotification, nil, [NSOperationQueue mainQueue],
^(MPLogsViewController *self, NSNotification *note) {
self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0;
} );
self.logView.contentInset = UIEdgeInsetsMake( 64, 0, 93, 0 );
[self refresh:nil];
@ -46,13 +45,20 @@
self.levelControl.selectedSegmentIndex = [[MPiOSConfig get].traceMode boolValue]? 1: 0;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
PearlRemoveNotificationObservers();
}
- (IBAction)toggleLevelControl:(UISegmentedControl *)sender {
BOOL traceEnabled = (BOOL)self.levelControl.selectedSegmentIndex;
if (traceEnabled) {
[PearlAlert showAlertWithTitle:@"Enable Trace Mode?" message:
@"Trace mode will log the internal operation of the application.\n"
@"Unless you're looking for the cause of a problem, you should leave this off to save memory."
@"Trace mode will log the internal operation of the application.\n"
@"Unless you're looking for the cause of a problem, you should leave this off to save memory."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
if (buttonIndex == [alert cancelButtonIndex])
@ -74,8 +80,8 @@
if ([[MPiOSConfig get].traceMode boolValue]) {
[PearlAlert showAlertWithTitle:@"Hiding Trace Messages" message:
@"Trace-level log messages will not be mailed. "
@"These messages contain sensitive and personal information."
@"Trace-level log messages will not be mailed. "
@"These messages contain sensitive and personal information."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
[[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self];

View File

@ -23,4 +23,7 @@
@end
@interface MPOverlaySegue : UIStoryboardSegue
+ (instancetype)dismissViewController:(UIViewController *)viewController;
@end

View File

@ -52,17 +52,20 @@
return [[MPOverlaySegue alloc] initWithIdentifier:identifier source:fromViewController destination:toViewController];
}
- (void)addDismissButtonForSegue:(MPOverlaySegue *)segue {
- (UIView *)addDismissButtonForSegue:(MPOverlaySegue *)segue {
UIButton *dismissButton = [UIButton buttonWithType:UIButtonTypeCustom];
[dismissButton addTarget:self action:@selector( dismissOverlay: ) forControlEvents:UIControlEventTouchUpInside];
dismissButton.backgroundColor = [UIColor colorWithWhite:0 alpha:0.3f];
dismissButton.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5f];
dismissButton.alpha = 0;
dismissButton.frame = self.view.bounds;
dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] =
[[MPOverlaySegue alloc] initWithIdentifier:@"dismiss-overlay"
source:segue.destinationViewController destination:segue.sourceViewController];
[self.view addSubview:dismissButton];
return dismissButton;
}
- (void)dismissOverlay:(UIButton *)dismissButton {
@ -96,6 +99,11 @@
@implementation MPOverlaySegue
+ (instancetype)dismissViewController:(UIViewController *)viewController {
return [[self alloc] initWithIdentifier:nil source:viewController destination:viewController];
}
- (void)perform {
UIViewController *sourceViewController = self.sourceViewController;
@ -109,6 +117,7 @@
if (!destinationViewController.parentViewController) {
// Winding
[containerViewController addChildViewController:destinationViewController];
UIView *dismissButton = [containerViewController addDismissButtonForSegue:self];
destinationViewController.view.frame = containerViewController.view.bounds;
destinationViewController.view.translatesAutoresizingMaskIntoConstraints = YES;
@ -125,6 +134,7 @@
destinationViewController.view.transform = CGAffineTransformIdentity;
CGRectSetY( destinationViewController.view.frame, 0 );
destinationViewController.view.alpha = 1;
dismissButton.alpha = 1;
} completion:^(BOOL finished) {
[destinationViewController didMoveToParentViewController:containerViewController];
[containerViewController setNeedsStatusBarAppearanceUpdate];

View File

@ -22,7 +22,6 @@
#import "MPPopdownSegue.h"
#import "MPAppDelegate_Key.h"
#import "MPPasswordCell.h"
#import "UICollectionView+PearlReloadFromArray.h"
#import "MPAnswersViewController.h"
@interface MPPasswordsViewController()<NSFetchedResultsControllerDelegate>
@ -33,10 +32,6 @@
@end
@implementation MPPasswordsViewController {
__weak id _storeChangingObserver;
__weak id _storeChangedObserver;
__weak id _mocObserver;
NSArray *_notificationObservers;
__weak UITapGestureRecognizer *_passwordsDismissRecognizer;
NSFetchedResultsController *_fetchedResultsController;
UIColor *_backgroundColor;
@ -69,7 +64,6 @@
[super viewWillAppear:animated];
[self registerObservers];
[self observeStore];
[self updateConfigKey:nil];
[self updatePasswords];
}
@ -90,8 +84,7 @@
[super viewWillDisappear:animated];
[self removeObservers];
[self stopObservingStore];
PearlRemoveNotificationObservers();
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
@ -280,97 +273,49 @@ referenceSizeForHeaderInSection:(NSInteger)section {
- (void)registerObservers {
if ([_notificationObservers count])
return;
Weakify( self );
_notificationObservers = @[
[[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
self.passwordSelectionContainer.alpha = 0;
}],
[[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationWillEnterForegroundNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
[self updatePasswords];
}],
[[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationDidBecomeActiveNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
[UIView animateWithDuration:0.7f animations:^{
self.passwordSelectionContainer.alpha = 1;
}];
}],
[[NSNotificationCenter defaultCenter]
addObserverForName:MPSignedOutNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
_fetchedResultsController = nil;
self.passwordsSearchBar.text = nil;
[self.passwordCollectionView reloadData];
}],
[[NSNotificationCenter defaultCenter]
addObserverForName:MPCheckConfigNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self updateConfigKey:note.object];
}],
];
}
- (void)removeObservers {
for (id observer in _notificationObservers)
[[NSNotificationCenter defaultCenter] removeObserver:observer];
_notificationObservers = nil;
}
- (void)observeStore {
Weakify( self );
PearlRemoveNotificationObservers();
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
self.passwordSelectionContainer.alpha = 0;
} );
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
[self updatePasswords];
} );
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
[UIView animateWithDuration:0.7f animations:^{
self.passwordSelectionContainer.alpha = 1;
}];
} );
PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
_fetchedResultsController = nil;
self.passwordsSearchBar.text = nil;
[self.passwordCollectionView reloadData];
} );
PearlAddNotificationObserver( MPCheckConfigNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
[self updateConfigKey:note.object];
} );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
self->_fetchedResultsController = nil;
[self.passwordCollectionView reloadData];
} );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
[self updatePasswords];
[self registerObservers];
} );
NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
if (!_mocObserver && mainContext)
_mocObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:NSManagedObjectContextDidSaveNotification object:mainContext
queue:nil usingBlock:^(NSNotification *note) {
if (![[MPiOSAppDelegate get] activeUserInContext:mainContext])
if (mainContext)
PearlAddNotificationObserver( NSManagedObjectContextDidSaveNotification, mainContext, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
if (![[MPiOSAppDelegate get] activeUserInContext:note.object])
[[MPiOSAppDelegate get] signOutAnimated:YES];
}];
if (!_storeChangingObserver)
_storeChangingObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:NSPersistentStoreCoordinatorStoresWillChangeNotification object:nil
queue:nil usingBlock:^(NSNotification *note) {
Strongify( self );
self->_fetchedResultsController = nil;
if (self->_mocObserver)
[[NSNotificationCenter defaultCenter] removeObserver:self->_mocObserver];
[self.passwordCollectionView reloadData];
}];
if (!_storeChangedObserver)
_storeChangedObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:NSPersistentStoreCoordinatorStoresDidChangeNotification object:nil
queue:nil usingBlock:^(NSNotification *note) {
Strongify( self );
[self updatePasswords];
}];
}
- (void)stopObservingStore {
if (_mocObserver)
[[NSNotificationCenter defaultCenter] removeObserver:_mocObserver];
if (_storeChangingObserver)
[[NSNotificationCenter defaultCenter] removeObserver:_storeChangingObserver];
if (_storeChangedObserver)
[[NSNotificationCenter defaultCenter] removeObserver:_storeChangedObserver];
} );
}
- (void)updateConfigKey:(NSString *)key {
@ -454,7 +399,7 @@ referenceSizeForHeaderInSection:(NSInteger)section {
initWithFetchRequest:fetchRequest managedObjectContext:mainContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
}];
[self observeStore];
[self registerObservers];
}
return _fetchedResultsController;

View File

@ -50,15 +50,22 @@ PearlEnum( MPDevelopmentFuelConsumption,
}
}];
[[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
PearlAddNotificationObserver( NSUserDefaultsDidChangeNotification, nil, [NSOperationQueue mainQueue],
^(MPStoreViewController *self, NSNotification *note) {
[self updateProducts];
[self updateFuel];
}];
} );
[[MPiOSAppDelegate get] registerProductsObserver:self];
[self updateFuel];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
PearlRemoveNotificationObservers();
}
#pragma mark - UITableViewDelegate
- (MPStoreProductCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -221,7 +228,7 @@ PearlEnum( MPDevelopmentFuelConsumption,
}
CGFloat fuelRatio = weeklyFuelConsumption == 0? 0: fuel / weeklyFuelConsumption; /* x weeks worth of fuel left */
[self.fuelMeterConstraint updateConstant:MIN(0.5f, fuelRatio - 0.5f) * 160]; /* -80pt = 0 weeks left, 80pt = >=1 week left */
[self.fuelMeterConstraint updateConstant:MIN( 0.5f, fuelRatio - 0.5f ) * 160]; /* -80pt = 0 weeks left, 80pt = >=1 week left */
}
- (CGFloat)weeklyFuelConsumption {

View File

@ -22,9 +22,7 @@
#import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Store.h"
#import "MPAppDelegate_Key.h"
#import "PearlSizedTextView.h"
#import "MPWebViewController.h"
#import "UIView+FontScale.h"
typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
/** The users are all inactive */
@ -51,10 +49,6 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
@end
@implementation MPUsersViewController {
__weak id _storeChangingObserver;
__weak id _storeChangedObserver;
__weak id _mocObserver;
NSArray *_notificationObservers;
NSString *_masterPasswordChoice;
NSOperationQueue *_afterUpdates;
}
@ -89,8 +83,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
[super viewWillDisappear:animated];
[self removeObservers];
[self stopObservingStore];
PearlRemoveNotificationObservers();
[self.marqueeTipTimer invalidate];
}
@ -99,7 +92,6 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
[super viewDidAppear:animated];
[self observeStore];
[self registerObservers];
[self reloadUsers];
@ -475,15 +467,15 @@ referenceSizeForFooterInSection:(NSInteger)section {
if ([nextMarqueeString isEqualToString:[self.marqueeButton titleForState:UIControlStateNormal]])
return;
[UIView animateWithDuration:timer? 0.5: 0 animations:^{
[UIView animateWithDuration:timer? 0.5f: 0 animations:^{
self.marqueeButton.alpha = 0;
} completion:^(BOOL finished) {
if (!finished)
return;
[self.marqueeButton setTitle:nextMarqueeString forState:UIControlStateNormal];
[UIView animateWithDuration:timer? 0.5: 0 animations:^{
self.marqueeButton.alpha = 0.5;
[UIView animateWithDuration:timer? 0.5f: 0 animations:^{
self.marqueeButton.alpha = 0.5f;
}];
}];
}
@ -586,54 +578,27 @@ referenceSizeForFooterInSection:(NSInteger)section {
- (void)registerObservers {
if ([_notificationObservers count])
return;
Weakify( self );
_notificationObservers = @[
[[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
self.userSelectionContainer.alpha = 0;
}],
[[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationWillEnterForegroundNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
[self reloadUsers];
}],
[[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationDidBecomeActiveNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Strongify( self );
[UIView animateWithDuration:0.7f animations:^{
self.userSelectionContainer.alpha = 1;
}];
}],
];
[self removeKeyPathObservers];
[self observeKeyPath:@"avatarCollectionView.contentOffset" withBlock:
^(id from, id to, NSKeyValueChange cause, MPUsersViewController *_self) {
[_self updateAvatarVisibility];
}];
}
- (void)removeObservers {
for (id observer in _notificationObservers)
[[NSNotificationCenter defaultCenter] removeObserver:observer];
_notificationObservers = nil;
[self removeKeyPathObservers];
}
- (void)observeStore {
Weakify( self );
PearlRemoveNotificationObservers();
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
self.userSelectionContainer.alpha = 0;
} );
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
[self reloadUsers];
} );
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
[UIView animateWithDuration:0.5f animations:^{
self.userSelectionContainer.alpha = 1;
}];
} );
NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
[UIView animateWithDuration:0.3f animations:^{
@ -644,51 +609,31 @@ referenceSizeForFooterInSection:(NSInteger)section {
if (!mainContext && !self.storeLoadingActivity.isAnimating)
[self.storeLoadingActivity startAnimating];
if (!_mocObserver && mainContext)
_mocObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:NSManagedObjectContextObjectsDidChangeNotification object:mainContext
queue:nil usingBlock:^(NSNotification *note) {
Strongify( self );
NSSet *insertedObjects = note.userInfo[NSInsertedObjectsKey];
NSSet *deletedObjects = note.userInfo[NSDeletedObjectsKey];
if ([[NSSetUnion( insertedObjects, deletedObjects )
filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject isKindOfClass:[MPUserEntity class]];
}]] count])
[self reloadUsers];
}];
if (!_storeChangingObserver)
_storeChangingObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:NSPersistentStoreCoordinatorStoresWillChangeNotification object:nil
queue:nil usingBlock:^(NSNotification *note) {
Strongify( self );
if (self->_mocObserver)
[[NSNotificationCenter defaultCenter] removeObserver:self->_mocObserver];
self.userIDs = nil;
}];
if (!_storeChangedObserver)
_storeChangedObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:NSPersistentStoreCoordinatorStoresDidChangeNotification object:nil
queue:nil usingBlock:^(NSNotification *note) {
Strongify( self );
if (mainContext)
PearlAddNotificationObserver( NSManagedObjectContextObjectsDidChangeNotification, mainContext, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
NSSet *insertedObjects = note.userInfo[NSInsertedObjectsKey];
NSSet *deletedObjects = note.userInfo[NSDeletedObjectsKey];
if ([[NSSetUnion( insertedObjects, deletedObjects )
filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject isKindOfClass:[MPUserEntity class]];
}]] count])
[self reloadUsers];
}];
}
- (void)stopObservingStore {
if (_mocObserver)
[[NSNotificationCenter defaultCenter] removeObserver:_mocObserver];
if (_storeChangingObserver)
[[NSNotificationCenter defaultCenter] removeObserver:_storeChangingObserver];
if (_storeChangedObserver)
[[NSNotificationCenter defaultCenter] removeObserver:_storeChangedObserver];
} );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
self.userIDs = nil;
} );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
[self registerObservers];
[self reloadUsers];
} );
}
- (void)reloadUsers {
[self afterUpdatesMainQueue:^{
[self observeStore];
if (![MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
NSError *error = nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];

View File

@ -69,18 +69,15 @@
err( @"During Analytics Setup: %@", exception );
}
@try {
[[NSNotificationCenter defaultCenter] addObserverForName:MPCheckConfigNotification object:nil queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
[self updateConfigKey:note.object];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:kIASKAppSettingChanged object:nil queue:nil usingBlock:
^(NSNotification *note) {
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:note.object];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification object:nil queue:nil usingBlock:
^(NSNotification *note) {
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:nil];
}];
PearlAddNotificationObserver( MPCheckConfigNotification, nil, [NSOperationQueue mainQueue], ^(id self, NSNotification *note) {
[self updateConfigKey:note.object];
} );
PearlAddNotificationObserver( kIASKAppSettingChanged, nil, nil, ^(id self, NSNotification *note) {
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:note.object];
} );
PearlAddNotificationObserver( NSUserDefaultsDidChangeNotification, nil, nil, ^(id self, NSNotification *note) {
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:nil];
} );
#ifdef ADHOC
[PearlAlert showAlertWithTitle:@"Welcome, tester!" message:
@ -106,28 +103,27 @@
@try {
inf( @"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier] );
[[NSNotificationCenter defaultCenter] addObserverForName:MPFoundInconsistenciesNotification object:nil queue:nil usingBlock:
^(NSNotification *note) {
switch ((MPFixableResult)[note.userInfo[MPInconsistenciesFixResultUserKey] unsignedIntegerValue]) {
PearlAddNotificationObserver( MPFoundInconsistenciesNotification, nil, nil, ^(id self, NSNotification *note) {
switch ((MPFixableResult)[note.userInfo[MPInconsistenciesFixResultUserKey] unsignedIntegerValue]) {
case MPFixableResultNoProblems:
break;
case MPFixableResultProblemsFixed:
[PearlAlert showAlertWithTitle:@"Inconsistencies Fixed" message:
@"Some inconsistencies were detected in your sites.\n"
@"All issues were fixed."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
break;
case MPFixableResultProblemsNotFixed:
[PearlAlert showAlertWithTitle:@"Inconsistencies Found" message:
@"Some inconsistencies were detected in your sites.\n"
@"Not all issues could be fixed. Try signing in to each user or checking the logs."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
break;
}
}];
case MPFixableResultNoProblems:
break;
case MPFixableResultProblemsFixed:
[PearlAlert showAlertWithTitle:@"Inconsistencies Fixed" message:
@"Some inconsistencies were detected in your sites.\n"
@"All issues were fixed."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
break;
case MPFixableResultProblemsNotFixed:
[PearlAlert showAlertWithTitle:@"Inconsistencies Found" message:
@"Some inconsistencies were detected in your sites.\n"
@"Not all issues could be fixed. Try signing in to each user or checking the logs."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
break;
}
} );
PearlMainQueue( ^{
if ([[MPiOSConfig get].showSetup boolValue])

View File

@ -433,6 +433,7 @@
93D39156E806BB78E04F78B9 /* PearlSizedTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSizedTextView.m; sourceTree = "<group>"; };
93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppSettingsViewController.m; sourceTree = "<group>"; };
93D391943675426839501BB8 /* MPLogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogsViewController.h; sourceTree = "<group>"; };
93D391AA32F24290C424438E /* NSNotificationCenter+PearlEasyCleanup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+PearlEasyCleanup.h"; sourceTree = "<group>"; };
93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadFromArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionView+PearlReloadFromArray.h"; sourceTree = "<group>"; };
93D3924D6F77E6BF41AC32D3 /* MPRootSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRootSegue.h; sourceTree = "<group>"; };
93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsViewController.m; sourceTree = "<group>"; };
@ -2632,6 +2633,7 @@
DAFE45F915039823003ABA7C /* Resources */,
93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */,
93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */,
93D391AA32F24290C424438E /* NSNotificationCenter+PearlEasyCleanup.h */,
);
path = Pearl;
sourceTree = "<group>";