2
0

Some usability improvements + apptentive fixes.

[IMPROVED]  Make persistence more lazy to avoid UI blocks.
[IMPROVED]  Use "Master Password" as CFBundleDisplayName at runtime.  No
            home-screen length restrictions there.
[FIXED]     Inform Apptentive of significant events.
This commit is contained in:
Maarten Billemont 2012-05-27 14:26:13 +02:00
parent ac14b10752
commit 7d0ea4b3f5
11 changed files with 170 additions and 119 deletions

2
.gitmodules vendored
View File

@ -6,7 +6,7 @@
url = git://github.com/futuretap/InAppSettingsKit.git url = git://github.com/futuretap/InAppSettingsKit.git
[submodule "External/iCloudStoreManager"] [submodule "External/iCloudStoreManager"]
path = External/iCloudStoreManager path = External/iCloudStoreManager
url = git://github.com/alekseyn/iCloudStoreManager.git url = git://github.com/lhunath/iCloudStoreManager.git
[submodule "External/apptentive"] [submodule "External/apptentive"]
path = External/apptentive path = External/apptentive
url = git://github.com/apptentive/apptentive-ios.git url = git://github.com/apptentive/apptentive-ios.git

2
External/Pearl vendored

@ -1 +1 @@
Subproject commit f92b0b1490e483d1bd4b8b6d1b9482c7ecfd4e44 Subproject commit 046dba155843d7a10d5c087e5b1d698ab271df67

@ -1 +1 @@
Subproject commit 6c19d5aa27b07d9a55cd19b003c4383b055b995f Subproject commit 84c718a57d64933e626d3756993fce513ad2bc2a

View File

@ -18,6 +18,13 @@
DA0A1D1215690AD40092735D /* tip_arrow_wood.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */; }; DA0A1D1215690AD40092735D /* tip_arrow_wood.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */; };
DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1315690AF30092735D /* Icon-72@2x.png */; }; DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1315690AF30092735D /* Icon-72@2x.png */; };
DA0A1D1615690AF40092735D /* Icon-Small-50@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */; }; DA0A1D1615690AF40092735D /* Icon-Small-50@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */; };
DA30E9CE15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */; };
DA30E9CF15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */; };
DA30E9D015722ECA00A68B4C /* Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CD15722ECA00A68B4C /* Pearl.m */; };
DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */; };
DA30E9D415722EF400A68B4C /* Pearl-UIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */; };
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9D515723E6900A68B4C /* PearlLazy.h */; };
DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D615723E6900A68B4C /* PearlLazy.m */; };
DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DA4426001557BF260052177D /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4425F11557BF260052177D /* UbiquityStoreManager.h */; }; DA4426001557BF260052177D /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4425F11557BF260052177D /* UbiquityStoreManager.h */; };
DA4426011557BF260052177D /* UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4425F21557BF260052177D /* UbiquityStoreManager.m */; }; DA4426011557BF260052177D /* UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4425F21557BF260052177D /* UbiquityStoreManager.m */; };
@ -925,6 +932,13 @@
DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tip_arrow_wood.png; path = Resources/Tooltips/tip_arrow_wood.png; sourceTree = SOURCE_ROOT; }; DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tip_arrow_wood.png; path = Resources/Tooltips/tip_arrow_wood.png; sourceTree = SOURCE_ROOT; };
DA0A1D1315690AF30092735D /* Icon-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72@2x.png"; sourceTree = "<group>"; }; DA0A1D1315690AF30092735D /* Icon-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72@2x.png"; sourceTree = "<group>"; };
DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50@2x.png"; sourceTree = "<group>"; }; DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50@2x.png"; sourceTree = "<group>"; };
DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSBundle_PearlMutableInfo.h; sourceTree = "<group>"; };
DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSBundle_PearlMutableInfo.m; sourceTree = "<group>"; };
DA30E9CD15722ECA00A68B4C /* Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Pearl.m; sourceTree = "<group>"; };
DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-Crypto.m"; sourceTree = "<group>"; };
DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-UIKit.m"; sourceTree = "<group>"; };
DA30E9D515723E6900A68B4C /* PearlLazy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLazy.h; sourceTree = "<group>"; };
DA30E9D615723E6900A68B4C /* PearlLazy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLazy.m; sourceTree = "<group>"; };
DA4425CB1557BED40052177D /* libiCloudStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiCloudStoreManager.a; sourceTree = BUILT_PRODUCTS_DIR; }; DA4425CB1557BED40052177D /* libiCloudStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiCloudStoreManager.a; sourceTree = BUILT_PRODUCTS_DIR; };
DA4425F11557BF260052177D /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = "<group>"; }; DA4425F11557BF260052177D /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = "<group>"; };
DA4425F21557BF260052177D /* UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UbiquityStoreManager.m; sourceTree = "<group>"; }; DA4425F21557BF260052177D /* UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UbiquityStoreManager.m; sourceTree = "<group>"; };
@ -2892,6 +2906,8 @@
DAFE45D715039823003ABA7C /* Pearl */ = { DAFE45D715039823003ABA7C /* Pearl */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */,
DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */,
DAFE45D815039823003ABA7C /* NSObject_PearlExport.h */, DAFE45D815039823003ABA7C /* NSObject_PearlExport.h */,
DAFE45D915039823003ABA7C /* NSObject_PearlExport.m */, DAFE45D915039823003ABA7C /* NSObject_PearlExport.m */,
DAFE45DA15039823003ABA7C /* NSString_PearlNSArrayFormat.h */, DAFE45DA15039823003ABA7C /* NSString_PearlNSArrayFormat.h */,
@ -2899,6 +2915,7 @@
DAFE45DC15039823003ABA7C /* NSString_PearlSEL.h */, DAFE45DC15039823003ABA7C /* NSString_PearlSEL.h */,
DAFE45DD15039823003ABA7C /* NSString_PearlSEL.m */, DAFE45DD15039823003ABA7C /* NSString_PearlSEL.m */,
DAFE45DE15039823003ABA7C /* Pearl.h */, DAFE45DE15039823003ABA7C /* Pearl.h */,
DA30E9CD15722ECA00A68B4C /* Pearl.m */,
DAFE45DF15039823003ABA7C /* PearlAbstractStrings.h */, DAFE45DF15039823003ABA7C /* PearlAbstractStrings.h */,
DAFE45E015039823003ABA7C /* PearlAbstractStrings.m */, DAFE45E015039823003ABA7C /* PearlAbstractStrings.m */,
DAFE45E315039823003ABA7C /* PearlCodeUtils.h */, DAFE45E315039823003ABA7C /* PearlCodeUtils.h */,
@ -2909,6 +2926,8 @@
DAFE45E815039823003ABA7C /* PearlDeviceUtils.m */, DAFE45E815039823003ABA7C /* PearlDeviceUtils.m */,
DAFE45E915039823003ABA7C /* PearlInfoPlist.h */, DAFE45E915039823003ABA7C /* PearlInfoPlist.h */,
DAFE45EA15039823003ABA7C /* PearlInfoPlist.m */, DAFE45EA15039823003ABA7C /* PearlInfoPlist.m */,
DA30E9D515723E6900A68B4C /* PearlLazy.h */,
DA30E9D615723E6900A68B4C /* PearlLazy.m */,
DAFE45EB15039823003ABA7C /* PearlLogger.h */, DAFE45EB15039823003ABA7C /* PearlLogger.h */,
DAFE45EC15039823003ABA7C /* PearlLogger.m */, DAFE45EC15039823003ABA7C /* PearlLogger.m */,
DAFE45ED15039823003ABA7C /* PearlMathUtils.h */, DAFE45ED15039823003ABA7C /* PearlMathUtils.h */,
@ -2940,6 +2959,7 @@
children = ( children = (
DA79A9BB1557DB6F00BAA07A /* libscryptenc-ios.a */, DA79A9BB1557DB6F00BAA07A /* libscryptenc-ios.a */,
DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */, DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */,
DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */,
DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */, DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */,
DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */, DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */,
DAFE460015039823003ABA7C /* PearlKeyChain.h */, DAFE460015039823003ABA7C /* PearlKeyChain.h */,
@ -2959,6 +2979,7 @@
children = ( children = (
DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */, DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */,
DAFE460915039823003ABA7C /* Pearl-UIKit.h */, DAFE460915039823003ABA7C /* Pearl-UIKit.h */,
DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */,
DAFE460A15039823003ABA7C /* PearlAlert.h */, DAFE460A15039823003ABA7C /* PearlAlert.h */,
DAFE460B15039823003ABA7C /* PearlAlert.m */, DAFE460B15039823003ABA7C /* PearlAlert.m */,
DAFE4A60150399FF003ABA7C /* PearlAppDelegate.m */, DAFE4A60150399FF003ABA7C /* PearlAppDelegate.m */,
@ -3094,6 +3115,8 @@
DAFE4A5615039824003ABA7C /* PearlWebViewController.h in Headers */, DAFE4A5615039824003ABA7C /* PearlWebViewController.h in Headers */,
DAFE4A5815039824003ABA7C /* UIImage_PearlScaling.h in Headers */, DAFE4A5815039824003ABA7C /* UIImage_PearlScaling.h in Headers */,
DAFE4A63150399FF003ABA7C /* PearlAppDelegate.h in Headers */, DAFE4A63150399FF003ABA7C /* PearlAppDelegate.h in Headers */,
DA30E9CE15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h in Headers */,
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -4141,6 +4164,11 @@
DAFE4A5715039824003ABA7C /* PearlWebViewController.m in Sources */, DAFE4A5715039824003ABA7C /* PearlWebViewController.m in Sources */,
DAFE4A5915039824003ABA7C /* UIImage_PearlScaling.m in Sources */, DAFE4A5915039824003ABA7C /* UIImage_PearlScaling.m in Sources */,
DAFE4A62150399FF003ABA7C /* PearlAppDelegate.m in Sources */, DAFE4A62150399FF003ABA7C /* PearlAppDelegate.m in Sources */,
DA30E9CF15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m in Sources */,
DA30E9D015722ECA00A68B4C /* Pearl.m in Sources */,
DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */,
DA30E9D415722EF400A68B4C /* Pearl-UIKit.m in Sources */,
DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -63,14 +63,23 @@
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Production" buildConfiguration = "AppStore"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
BuildableName = "MasterPassword.app"
BlueprintName = "MasterPassword"
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction
buildConfiguration = "Debug"> buildConfiguration = "Debug">
</AnalyzeAction> </AnalyzeAction>
<ArchiveAction <ArchiveAction
buildConfiguration = "Production" buildConfiguration = "AppStore"
revealArchiveInOrganizer = "YES"> revealArchiveInOrganizer = "YES">
</ArchiveAction> </ArchiveAction>
</Scheme> </Scheme>

View File

@ -42,28 +42,37 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
if (managedObjectContext) if (managedObjectContext)
return managedObjectContext; return managedObjectContext;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; return [PearlLazy lazyObjectLoadedFrom:^id{
assert(coordinator); NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
assert(coordinator);
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[managedObjectContext performBlockAndWait:^{ [managedObjectContext performBlockAndWait:^{
managedObjectContext.persistentStoreCoordinator = coordinator; managedObjectContext.persistentStoreCoordinator = coordinator;
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
}];
return managedObjectContext;
}]; }];
return managedObjectContext;
} }
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// Wait until the storeManager is ready. // Start loading the store.
for(__block BOOL isReady = [self storeManager].isReady; !isReady;) [self storeManager];
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
isReady = [self storeManager].isReady;
});
assert([self storeManager].isReady); return [PearlLazy lazyObjectLoadedFrom:^id{
return [self storeManager].persistentStoreCoordinator; // Wait until the storeManager is ready.
for(__block BOOL isReady = [self storeManager].isReady; !isReady;) {
[NSThread sleepForTimeInterval:0.1];
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
isReady = [self storeManager].isReady;
});
}
assert([self storeManager].isReady);
return [self storeManager].persistentStoreCoordinator;
}];
} }
- (UbiquityStoreManager *)storeManager { - (UbiquityStoreManager *)storeManager {

View File

@ -148,6 +148,8 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[[NSBundle mainBundle] mutableLocalizedInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
#ifndef DEBUG #ifndef DEBUG
@try { @try {
@ -212,9 +214,28 @@
NSString *apptentiveAPIKey = [self apptentiveAPIKey]; NSString *apptentiveAPIKey = [self apptentiveAPIKey];
if ([apptentiveAPIKey length]) { if ([apptentiveAPIKey length]) {
dbg(@"Initializing Apptentive"); dbg(@"Initializing Apptentive");
ATConnect *connection = [ATConnect sharedConnection]; ATConnect *connection = [ATConnect sharedConnection];
connection.shouldTakeScreenshot = NO; [connection setApiKey:apptentiveAPIKey];
connection.apiKey = apptentiveAPIKey; [connection setShouldTakeScreenshot:NO];
[connection addAdditionalInfoToFeedback:[PearlInfoPlist get].CFBundleVersion withKey:@"CFBundleVersion"];
ATAppRatingFlow *ratingsFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:nil queue:nil
usingBlock:^(NSNotification *note) {
dispatch_async(dispatch_get_main_queue(), ^{
[ratingsFlow appDidEnterForeground:YES
viewController:self.navigationController];
});
}];
[[NSNotificationCenter defaultCenter] addObserverForName:MPNotificationKeySet object:nil queue:nil
usingBlock:^(NSNotification *note) {
dispatch_async(dispatch_get_main_queue(), ^{
[ratingsFlow userDidPerformSignificantEvent:YES
viewController:self.navigationController];
});
}];
[ratingsFlow appDidLaunch:YES viewController:self.navigationController];
} }
} }
@catch (NSException *exception) { @catch (NSException *exception) {
@ -288,14 +309,6 @@
@"https://youtrack.lyndir.com\n" @"https://youtrack.lyndir.com\n"
viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil
cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil]; cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
#else
@try {
ATAppRatingFlow *sharedFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID];
[sharedFlow appDidLaunch:YES viewController:self.navigationController];
}
@catch (NSException *exception) {
err(@"Apptentive: %@", exception);
}
#endif #endif
[[UIApplication sharedApplication] setStatusBarHidden:NO [[UIApplication sharedApplication] setStatusBarHidden:NO
@ -378,9 +391,6 @@
[TestFlight passCheckpoint:MPTestFlightCheckpointActivated]; [TestFlight passCheckpoint:MPTestFlightCheckpointActivated];
ATAppRatingFlow *sharedFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID];
[sharedFlow appDidEnterForeground:YES viewController:self.navigationController];
[super applicationDidBecomeActive:application]; [super applicationDidBecomeActive:application];
} }
@ -541,7 +551,7 @@
static NSDictionary *apptentiveInfo = nil; static NSDictionary *apptentiveInfo = nil;
if (apptentiveInfo == nil) if (apptentiveInfo == nil)
apptentiveInfo = [[NSDictionary alloc] initWithContentsOfURL: apptentiveInfo = [[NSDictionary alloc] initWithContentsOfURL:
[[NSBundle mainBundle] URLForResource:@"Apptentive" withExtension:@"plist"]]; [[NSBundle mainBundle] URLForResource:@"Apptentive" withExtension:@"plist"]];
return apptentiveInfo; return apptentiveInfo;
} }

View File

@ -146,8 +146,6 @@
- (void)updateAnimated:(BOOL)animated { - (void)updateAnimated:(BOOL)animated {
[[MPAppDelegate get] saveContext];
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (animated) if (animated)
[UIView animateWithDuration:0.3f animations:^{ [UIView animateWithDuration:0.3f animations:^{
@ -352,6 +350,7 @@
NSString *oldPassword = [self.activeElement.content description]; NSString *oldPassword = [self.activeElement.content description];
task(); task();
NSString *newPassword = [self.activeElement.content description]; NSString *newPassword = [self.activeElement.content description];
[[MPAppDelegate get] saveContext];
[self updateAnimated:YES]; [self updateAnimated:YES];
// Show new and old password. // Show new and old password.

View File

@ -14,7 +14,6 @@
@interface MPSearchDelegate (Private) @interface MPSearchDelegate (Private)
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath; - (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath;
- (void)update;
@end @end
@ -38,10 +37,14 @@
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])]; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]]; fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest self.fetchedResultsController = [PearlLazy lazyObjectLoadedFrom:^id{
managedObjectContext:[MPAppDelegate managedObjectContext] NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
sectionNameKeyPath:nil cacheName:nil]; managedObjectContext:[MPAppDelegate managedObjectContext]
self.fetchedResultsController.delegate = self; sectionNameKeyPath:nil cacheName:nil];
controller.delegate = self;
return controller;
}];
self.tipView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 170)]; self.tipView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 170)];
self.tipView.textAlignment = UITextAlignmentCenter; self.tipView.textAlignment = UITextAlignmentCenter;
@ -123,12 +126,8 @@
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self update]; if (!controller.active)
return NO;
return NO;
}
- (void)update {
assert(self.query); assert(self.query);
@ -138,7 +137,6 @@
NSError *error; NSError *error;
if (![self.fetchedResultsController performFetch:&error]) if (![self.fetchedResultsController performFetch:&error])
err(@"Couldn't fetch elements: %@", error); err(@"Couldn't fetch elements: %@", error);
[self.searchDisplayController.searchResultsTableView reloadData];
NSArray *subviews = self.searchDisplayController.searchBar.superview.subviews; NSArray *subviews = self.searchDisplayController.searchBar.superview.subviews;
NSUInteger overlayIndex = [subviews indexOfObject:self.searchDisplayController.searchBar] + 1; NSUInteger overlayIndex = [subviews indexOfObject:self.searchDisplayController.searchBar] + 1;
@ -149,6 +147,8 @@
[self.tipView removeFromSuperview]; [self.tipView removeFromSuperview];
[overlay addSubview:self.tipView]; [overlay addSubview:self.tipView];
} }
return YES;
} }
// See MP-14, also crashes easily on internal assertions etc.. // See MP-14, also crashes easily on internal assertions etc..

View File

@ -152,73 +152,69 @@ typedef enum {
- (void)textFieldDidEndEditing:(UITextField *)textField { - (void)textFieldDidEndEditing:(UITextField *)textField {
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
rotate.fromValue = [NSNumber numberWithFloat:0];
rotate.toValue = [NSNumber numberWithFloat:2 * M_PI];
rotate.repeatCount = MAXFLOAT;
rotate.duration = 3.0;
[self.spinner.layer removeAllAnimations];
[self.spinner.layer addAnimation:rotate forKey:@"transform"];
[UIView animateWithDuration:0.3f animations:^{
self.spinner.alpha = 1.0f;
}];
[self showMessage:@"Checking password..." state:MPLockscreenProgress];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@try { BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:textField.text];
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; if (unlocked) {
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; [self showMessage:@"Success!" state:MPLockscreenSuccess];
rotate.fromValue = [NSNumber numberWithFloat:0];
rotate.toValue = [NSNumber numberWithFloat:2 * M_PI];
rotate.repeatCount = MAXFLOAT;
rotate.duration = 3.0;
[self.spinner.layer removeAllAnimations]; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
[self.spinner.layer addAnimation:rotate forKey:@"transform"]; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"keyID == %@", [MPAppDelegate get].keyID];
fetchRequest.fetchLimit = 1;
[UIView animateWithDuration:0.3f animations:^{ BOOL keyIDHasElements = [[[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil] count] > 0;
self.spinner.alpha = 1.0f; if (keyIDHasElements)
}]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long)(NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{
[self dismissModalViewControllerAnimated:YES];
[self showMessage:@"Checking password..." state:MPLockscreenProgress]; });
}); else {
[PearlAlert showAlertWithTitle:@"New Master Password"
if ([[MPAppDelegate get] tryMasterPassword:textField.text]) message:
dispatch_async(dispatch_get_main_queue(), ^{ @"Please confirm the spelling of this new master password."
[self showMessage:@"Success!" state:MPLockscreenSuccess]; viewStyle:UIAlertViewStyleSecureTextInput
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])]; if (buttonIndex == [alert cancelButtonIndex]) {
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"keyID == %@", [MPAppDelegate get].keyID]; [[MPAppDelegate get] updateKey:nil];
fetchRequest.fetchLimit = 1; return;
BOOL keyIDHasElements = [[[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil] count] > 0;
if (keyIDHasElements)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long)(NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{
[self dismissModalViewControllerAnimated:YES];
});
else {
[PearlAlert showAlertWithTitle:@"New Master Password"
message:
@"Please confirm the spelling of this new master password."
viewStyle:UIAlertViewStyleSecureTextInput
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
if (buttonIndex == [alert cancelButtonIndex]) {
[[MPAppDelegate get] updateKey:nil];
return;
}
if (![[alert textFieldAtIndex:0].text isEqualToString:textField.text]) {
[PearlAlert showAlertWithTitle:@"Incorrect Master Password"
message:
@"The password you entered doesn't match with the master password you tried to use. "
@"You've probably mistyped one of them.\n\n"
@"Give it another try."
viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil
cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
return;
}
[self dismissModalViewControllerAnimated:YES];
} }
cancelTitle:[PearlStrings get].commonButtonCancel if (![[alert textFieldAtIndex:0].text isEqualToString:textField.text]) {
otherTitles:[PearlStrings get].commonButtonContinue, nil]; [PearlAlert showAlertWithTitle:@"Incorrect Master Password"
} message:
}); @"The password you entered doesn't match with the master password you tried to use. "
else @"You've probably mistyped one of them.\n\n"
dispatch_async(dispatch_get_main_queue(), ^{ @"Give it another try."
[self showMessage:@"Not valid." state:MPLockscreenError]; viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil
[UIView animateWithDuration:0.5f animations:^{ cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
self.changeMPView.alpha = 1.0f; return;
}]; }
}); [self dismissModalViewControllerAnimated:YES];
} }
@finally { cancelTitle:[PearlStrings get].commonButtonCancel
otherTitles:[PearlStrings get].commonButtonContinue, nil];
}
} else {
[self showMessage:@"Not valid." state:MPLockscreenError];
[UIView animateWithDuration:0.5f animations:^{
self.changeMPView.alpha = 1.0f;
}];
}
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.3f animations:^{ [UIView animateWithDuration:0.3f animations:^{
self.spinner.alpha = 0.0f; self.spinner.alpha = 0.0f;
@ -226,7 +222,7 @@ typedef enum {
[self.spinner.layer removeAllAnimations]; [self.spinner.layer removeAllAnimations];
}]; }];
}); });
} });
}); });
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB