From 87490ab0406d0a57668c34cbeeb7c41c7e209d09 Mon Sep 17 00:00:00 2001 From: Dasmer Singh Date: Tue, 30 Jun 2015 16:54:41 -0400 Subject: [PATCH 1/4] Add lock completion enums, refactor lock to use touchID --- VENTouchLock/VENTouchLock.h | 13 ++ VENTouchLock/VENTouchLock.m | 251 ++++++++++++++++++++++++------------ 2 files changed, 184 insertions(+), 80 deletions(-) diff --git a/VENTouchLock/VENTouchLock.h b/VENTouchLock/VENTouchLock.h index cf28ed4..1bff0be 100644 --- a/VENTouchLock/VENTouchLock.h +++ b/VENTouchLock/VENTouchLock.h @@ -4,6 +4,14 @@ #import "VENTouchLockSplashViewController.h" #import "VENTouchLockOptions.h" +typedef NS_ENUM(NSUInteger, VENTouchLockCompletion) { + VENTouchLockCompletionUndefined, + VENTouchLockCompletionFingerprintUnlock, + VENTouchLockCompletionPasscodeUnlock, + VENTouchLockCompletionPasscodeLimitReached, + VENTouchLockCompletionCancel +}; + typedef NS_ENUM(NSUInteger, VENTouchLockTouchIDResponse) { VENTouchLockTouchIDResponseUndefined, VENTouchLockTouchIDResponseSuccess, @@ -19,6 +27,11 @@ typedef NS_ENUM(NSUInteger, VENTouchLockTouchIDResponse) { */ @property (assign, nonatomic, readonly) BOOL locked; +/** + This block is called each time the TouchLock is unlocked or dismissed. + */ +@property (nonatomic, copy) void (^lockCompletion)(VENTouchLockCompletion); + /** The class of a UIView subclass. When the app is in the background and the TouchLock is locked, an instance of this view, that is diff --git a/VENTouchLock/VENTouchLock.m b/VENTouchLock/VENTouchLock.m index 61a37e8..532d432 100644 --- a/VENTouchLock/VENTouchLock.m +++ b/VENTouchLock/VENTouchLock.m @@ -192,86 +192,52 @@ - (void)lock return; } - __weak typeof(self) weakSelf = self; BOOL fromBackground = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; - UIViewController *displayViewController; - UIView *snapshotView; - void (^displayPresentationCompletionBlock)(); + BOOL shouldUseSplash = ((self.splashViewControllerClass != NULL) + && ([self.splashViewControllerClass isSubclassOfClass:[VENTouchLockSplashViewController class]])); - if (self.splashViewControllerClass != NULL) { - VENTouchLockSplashViewController *splashViewController = [[self.splashViewControllerClass alloc] init]; + if (shouldUseSplash) { + VENTouchLockSplashViewController *splashViewController = [self splashViewController]; - void (^didFinishWithResult)(BOOL success, VENTouchLockSplashViewControllerUnlockType unlockType) = splashViewController.didFinishWithResult; + BOOL shouldEmbedInNavigationController = self.options.splashShouldEmbedInNavigationController; + UIViewController *displayViewController; + displayViewController = [self transformViewController:splashViewController byEmbedding:shouldEmbedInNavigationController]; - splashViewController.didFinishWithResult = ^(BOOL success, VENTouchLockSplashViewControllerUnlockType unlockType) { - __strong typeof(self) strongSelf = weakSelf; - dispatch_async(dispatch_get_main_queue(), ^{ - strongSelf.locked = NO; - if (didFinishWithResult) { - didFinishWithResult(success, unlockType); - } - }); - }; + self.locked = YES; - displayPresentationCompletionBlock = ^{ - [splashViewController showUnlockAnimated:NO]; - }; + if (fromBackground) { + VENTouchLockSplashViewController *snapshotSplashViewController = [[self.splashViewControllerClass alloc] init]; + UIViewController *snapshotDisplayController = [self transformViewController:snapshotSplashViewController byEmbedding:shouldEmbedInNavigationController]; + [snapshotDisplayController loadView]; + [snapshotDisplayController viewDidLoad]; + [self showSnapshotView:snapshotSplashViewController.view]; + } - if ([splashViewController isKindOfClass:[VENTouchLockSplashViewController class]]) { - if (self.options.splashShouldEmbedInNavigationController) { - displayViewController = [splashViewController ventouchlock_embeddedInNavigationControllerWithNavigationBarClass:self.options.navigationBarClass]; - } - else { - displayViewController = splashViewController; - } + [self presentViewControllerOnTop:displayViewController completion:^{ + [splashViewController showUnlockAnimated:NO]; + }]; - if (fromBackground) { - VENTouchLockSplashViewController *snapshotSplashViewController = [[self.splashViewControllerClass alloc] init]; - UIViewController *snapshotDisplayController; - if (self.options.splashShouldEmbedInNavigationController) { - snapshotDisplayController = [snapshotSplashViewController ventouchlock_embeddedInNavigationControllerWithNavigationBarClass:self.options.navigationBarClass]; - } - else { - snapshotDisplayController = snapshotSplashViewController; - } - [snapshotDisplayController loadView]; - [snapshotDisplayController viewDidLoad]; - snapshotView = snapshotDisplayController.view; - } - } } else { - VENTouchLockEnterPasscodeViewController *enterPasscodeViewController = [[VENTouchLockEnterPasscodeViewController alloc] initWithTouchLock:self]; - enterPasscodeViewController.didFinishWithResult = ^(BOOL success) { - __strong typeof(self) strongSelf = weakSelf; - dispatch_async(dispatch_get_main_queue(), ^{ - strongSelf.locked = NO; - }); - }; - if (self.options.passcodeViewControllerShouldEmbedInNavigationController) { - displayViewController = [enterPasscodeViewController ventouchlock_embeddedInNavigationControllerWithNavigationBarClass:self.options.navigationBarClass]; - } else { - displayViewController = enterPasscodeViewController; + if (self.shouldUseTouchID) { + [self showTouchID]; } + else { + VENTouchLockEnterPasscodeViewController *enterPasscodeViewController = [self enterPasscodeViewController]; - if (fromBackground && self.appSwitchViewClass != NULL) { - snapshotView = [[self.appSwitchViewClass alloc] initWithFrame:CGRectZero]; - } - } + BOOL shouldEmbedInNavigationController = self.options.passcodeViewControllerShouldEmbedInNavigationController; - self.locked = YES; + UIViewController *displayViewController = [self transformViewController:enterPasscodeViewController + byEmbedding:shouldEmbedInNavigationController]; - if (fromBackground && snapshotView) { - [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - UIWindow *mainWindow = [[UIApplication sharedApplication].windows firstObject]; - snapshotView.frame = mainWindow.bounds; - [mainWindow addSubview:snapshotView]; - self.snapshotView = snapshotView; - } + self.locked = YES; - dispatch_async(dispatch_get_main_queue(), ^{ - UIViewController *rootViewController = [UIViewController ventouchlock_topMostController]; - [rootViewController presentViewController:displayViewController animated:NO completion:displayPresentationCompletionBlock]; - }); + if (fromBackground && self.appSwitchViewClass != NULL) { + UIView *snapshotView = [[self.appSwitchViewClass alloc] init]; + [self showSnapshotView:snapshotView]; + } + [self presentViewControllerOnTop:displayViewController completion:nil]; + } + } } @@ -329,19 +295,6 @@ - (void)applicationWillEnterForeground:(NSNotification *)notification } -#pragma mark - Internal - -- (NSString *)keychainPasscodeAttemptAccountName -{ - return [self.keychainPasscodeAccount stringByAppendingString:@"_AttemptName"]; -} - -- (NSString *)keypathOfAutolockOptions -{ - return [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(options)), NSStringFromSelector(@selector(shouldAutoLockOnAppLifeCycleNotifications))]; -} - - #pragma mark - NSObject - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context @@ -373,8 +326,146 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N self.obscureView = nil; }]; } + } } } + + +#pragma mark - Internal Helper Methods + +- (void)showTouchID +{ + [self requestTouchIDWithCompletion:^(VENTouchLockTouchIDResponse response) { + switch (response) { + case VENTouchLockTouchIDResponseSuccess: { + self.locked = NO; + if (self.lockCompletion) { + self.lockCompletion(VENTouchLockCompletionPasscodeUnlock); + } + break; + } + case VENTouchLockTouchIDResponseCanceled: { + self.locked = NO; + if (self.lockCompletion) { + self.lockCompletion(VENTouchLockCompletionCancel); + } + break; + } + case VENTouchLockTouchIDResponseUsePasscode: { + VENTouchLockEnterPasscodeViewController *enterPasscodeViewController = [self enterPasscodeViewController]; + BOOL shouldEmbedInNavigationController = self.options.passcodeViewControllerShouldEmbedInNavigationController; + + UIViewController *displayViewController = [self transformViewController:enterPasscodeViewController + byEmbedding:shouldEmbedInNavigationController]; + [self presentViewControllerOnTop:displayViewController completion:nil]; + break; + } + + default: + break; + } + }]; +} + +- (void)showSnapshotView:(UIView *)snapshotView +{ + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + UIWindow *mainWindow = [[UIApplication sharedApplication].windows firstObject]; + snapshotView.frame = mainWindow.bounds; + [mainWindow addSubview:snapshotView]; + self.snapshotView = snapshotView; +} + + +- (void)presentViewControllerOnTop:(UIViewController *)viewController completion:(void (^)())completion +{ + dispatch_async(dispatch_get_main_queue(), ^{ + UIViewController *rootViewController = [UIViewController ventouchlock_topMostController]; + [rootViewController presentViewController:viewController animated:NO completion:completion]; + }); +} + +- (NSString *)keychainPasscodeAttemptAccountName +{ + return [self.keychainPasscodeAccount stringByAppendingString:@"_AttemptName"]; +} + +- (NSString *)keypathOfAutolockOptions +{ + return [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(options)), NSStringFromSelector(@selector(shouldAutoLockOnAppLifeCycleNotifications))]; +} + +- (VENTouchLockSplashViewController *)splashViewController +{ + VENTouchLockSplashViewController *splashViewController = [[self.splashViewControllerClass alloc] init]; + + void (^didFinishWithResult)(BOOL success, VENTouchLockSplashViewControllerUnlockType unlockType) = splashViewController.didFinishWithResult; + + __weak typeof(self) weakSelf = self; + splashViewController.didFinishWithResult = ^(BOOL success, VENTouchLockSplashViewControllerUnlockType unlockType) { + __strong typeof(self) strongSelf = weakSelf; + dispatch_async(dispatch_get_main_queue(), ^{ + strongSelf.locked = NO; + if (didFinishWithResult) { + didFinishWithResult(success, unlockType); + } + + VENTouchLockCompletion lockCompletion; + if (success) { + switch (unlockType) { + case VENTouchLockSplashViewControllerUnlockTypeTouchID: { + lockCompletion = VENTouchLockCompletionFingerprintUnlock; + break; + } + case VENTouchLockSplashViewControllerUnlockTypePasscode: { + lockCompletion = VENTouchLockCompletionPasscodeUnlock; + break; + } + default: { + lockCompletion = VENTouchLockCompletionUndefined; + break; + } + } + } else { + lockCompletion = VENTouchLockCompletionPasscodeLimitReached; + } + if (strongSelf.lockCompletion) { + self.lockCompletion(lockCompletion); + } + }); + }; + + return splashViewController; +} + +- (VENTouchLockEnterPasscodeViewController *)enterPasscodeViewController +{ + VENTouchLockEnterPasscodeViewController *enterPasscodeViewController = [[VENTouchLockEnterPasscodeViewController alloc] initWithTouchLock:self]; + + __weak typeof(self) weakSelf = self; + enterPasscodeViewController.didFinishWithResult = ^(BOOL success) { + __strong typeof(self) strongSelf = weakSelf; + dispatch_async(dispatch_get_main_queue(), ^{ + strongSelf.locked = NO; + VENTouchLockCompletion lockCompletion = success ? VENTouchLockCompletionPasscodeUnlock : VENTouchLockCompletionCancel; + if (strongSelf.lockCompletion) { + self.lockCompletion(lockCompletion); + } + }); + }; + return enterPasscodeViewController; +} + +- (UIViewController *)transformViewController:(UIViewController *)vc byEmbedding:(BOOL)shouldEmbed +{ + UIViewController *viewController; + if (shouldEmbed) { + viewController = [vc ventouchlock_embeddedInNavigationControllerWithNavigationBarClass:self.options.navigationBarClass]; + } + else { + viewController = vc; + } + return viewController; } @end From 9e859a7ec0784228f37d3db7519d651407d6535b Mon Sep 17 00:00:00 2001 From: Dasmer Singh Date: Tue, 30 Jun 2015 17:16:02 -0400 Subject: [PATCH 2/4] Fix syntax --- VENTouchLock/VENTouchLock.h | 2 +- VENTouchLock/VENTouchLock.m | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/VENTouchLock/VENTouchLock.h b/VENTouchLock/VENTouchLock.h index 1bff0be..7d52fff 100644 --- a/VENTouchLock/VENTouchLock.h +++ b/VENTouchLock/VENTouchLock.h @@ -6,7 +6,7 @@ typedef NS_ENUM(NSUInteger, VENTouchLockCompletion) { VENTouchLockCompletionUndefined, - VENTouchLockCompletionFingerprintUnlock, + VENTouchLockCompletionTouchIDUnlock, VENTouchLockCompletionPasscodeUnlock, VENTouchLockCompletionPasscodeLimitReached, VENTouchLockCompletionCancel diff --git a/VENTouchLock/VENTouchLock.m b/VENTouchLock/VENTouchLock.m index 532d432..27c3fbf 100644 --- a/VENTouchLock/VENTouchLock.m +++ b/VENTouchLock/VENTouchLock.m @@ -376,7 +376,6 @@ - (void)showSnapshotView:(UIView *)snapshotView self.snapshotView = snapshotView; } - - (void)presentViewControllerOnTop:(UIViewController *)viewController completion:(void (^)())completion { dispatch_async(dispatch_get_main_queue(), ^{ @@ -414,7 +413,7 @@ - (VENTouchLockSplashViewController *)splashViewController if (success) { switch (unlockType) { case VENTouchLockSplashViewControllerUnlockTypeTouchID: { - lockCompletion = VENTouchLockCompletionFingerprintUnlock; + lockCompletion = VENTouchLockCompletionTouchIDUnlock; break; } case VENTouchLockSplashViewControllerUnlockTypePasscode: { From 25cc77443ceb2145411c9a39e991f901b8dfc7ba Mon Sep 17 00:00:00 2001 From: Dasmer Singh Date: Tue, 30 Jun 2015 18:20:05 -0400 Subject: [PATCH 3/4] VENTouchLockCompletion -> VENTouchLockCompletionType --- VENTouchLock/VENTouchLock.h | 14 +++++++------- VENTouchLock/VENTouchLock.m | 18 ++++++++++-------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/VENTouchLock/VENTouchLock.h b/VENTouchLock/VENTouchLock.h index 7d52fff..dce7831 100644 --- a/VENTouchLock/VENTouchLock.h +++ b/VENTouchLock/VENTouchLock.h @@ -4,12 +4,12 @@ #import "VENTouchLockSplashViewController.h" #import "VENTouchLockOptions.h" -typedef NS_ENUM(NSUInteger, VENTouchLockCompletion) { - VENTouchLockCompletionUndefined, - VENTouchLockCompletionTouchIDUnlock, - VENTouchLockCompletionPasscodeUnlock, - VENTouchLockCompletionPasscodeLimitReached, - VENTouchLockCompletionCancel +typedef NS_ENUM(NSUInteger, VENTouchLockCompletionType) { + VENTouchLockCompletionTypeUndefined, + VENTouchLockCompletionTypeTouchIDUnlock, + VENTouchLockCompletionTypePasscodeUnlock, + VENTouchLockCompletionTypePasscodeLimitReached, + VENTouchLockCompletionTypeCancel }; typedef NS_ENUM(NSUInteger, VENTouchLockTouchIDResponse) { @@ -30,7 +30,7 @@ typedef NS_ENUM(NSUInteger, VENTouchLockTouchIDResponse) { /** This block is called each time the TouchLock is unlocked or dismissed. */ -@property (nonatomic, copy) void (^lockCompletion)(VENTouchLockCompletion); +@property (nonatomic, copy) void (^lockCompletion)(VENTouchLockCompletionType); /** The class of a UIView subclass. diff --git a/VENTouchLock/VENTouchLock.m b/VENTouchLock/VENTouchLock.m index 27c3fbf..1caafb5 100644 --- a/VENTouchLock/VENTouchLock.m +++ b/VENTouchLock/VENTouchLock.m @@ -196,6 +196,8 @@ - (void)lock BOOL shouldUseSplash = ((self.splashViewControllerClass != NULL) && ([self.splashViewControllerClass isSubclassOfClass:[VENTouchLockSplashViewController class]])); + self.locked = YES; + if (shouldUseSplash) { VENTouchLockSplashViewController *splashViewController = [self splashViewController]; @@ -340,14 +342,14 @@ - (void)showTouchID case VENTouchLockTouchIDResponseSuccess: { self.locked = NO; if (self.lockCompletion) { - self.lockCompletion(VENTouchLockCompletionPasscodeUnlock); + self.lockCompletion(VENTouchLockCompletionTypePasscodeUnlock); } break; } case VENTouchLockTouchIDResponseCanceled: { self.locked = NO; if (self.lockCompletion) { - self.lockCompletion(VENTouchLockCompletionCancel); + self.lockCompletion(VENTouchLockCompletionTypeCancel); } break; } @@ -409,24 +411,24 @@ - (VENTouchLockSplashViewController *)splashViewController didFinishWithResult(success, unlockType); } - VENTouchLockCompletion lockCompletion; + VENTouchLockCompletionType lockCompletion; if (success) { switch (unlockType) { case VENTouchLockSplashViewControllerUnlockTypeTouchID: { - lockCompletion = VENTouchLockCompletionTouchIDUnlock; + lockCompletion = VENTouchLockCompletionTypeTouchIDUnlock; break; } case VENTouchLockSplashViewControllerUnlockTypePasscode: { - lockCompletion = VENTouchLockCompletionPasscodeUnlock; + lockCompletion = VENTouchLockCompletionTypePasscodeUnlock; break; } default: { - lockCompletion = VENTouchLockCompletionUndefined; + lockCompletion = VENTouchLockCompletionTypeUndefined; break; } } } else { - lockCompletion = VENTouchLockCompletionPasscodeLimitReached; + lockCompletion = VENTouchLockCompletionTypePasscodeLimitReached; } if (strongSelf.lockCompletion) { self.lockCompletion(lockCompletion); @@ -446,7 +448,7 @@ - (VENTouchLockEnterPasscodeViewController *)enterPasscodeViewController __strong typeof(self) strongSelf = weakSelf; dispatch_async(dispatch_get_main_queue(), ^{ strongSelf.locked = NO; - VENTouchLockCompletion lockCompletion = success ? VENTouchLockCompletionPasscodeUnlock : VENTouchLockCompletionCancel; + VENTouchLockCompletionType lockCompletion = success ? VENTouchLockCompletionTypePasscodeUnlock : VENTouchLockCompletionTypeCancel; if (strongSelf.lockCompletion) { self.lockCompletion(lockCompletion); } From d4088410931a8a3c2c974c685d7d97997eb9c6fb Mon Sep 17 00:00:00 2001 From: Dasmer Singh Date: Tue, 30 Jun 2015 18:20:47 -0400 Subject: [PATCH 4/4] showTouchID on Foreground --- VENTouchLock/VENTouchLock.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/VENTouchLock/VENTouchLock.m b/VENTouchLock/VENTouchLock.m index 1caafb5..1070310 100644 --- a/VENTouchLock/VENTouchLock.m +++ b/VENTouchLock/VENTouchLock.m @@ -205,8 +205,6 @@ - (void)lock UIViewController *displayViewController; displayViewController = [self transformViewController:splashViewController byEmbedding:shouldEmbedInNavigationController]; - self.locked = YES; - if (fromBackground) { VENTouchLockSplashViewController *snapshotSplashViewController = [[self.splashViewControllerClass alloc] init]; UIViewController *snapshotDisplayController = [self transformViewController:snapshotSplashViewController byEmbedding:shouldEmbedInNavigationController]; @@ -221,7 +219,9 @@ - (void)lock } else { if (self.shouldUseTouchID) { - [self showTouchID]; + if (!fromBackground) { + [self showTouchID]; + } } else { VENTouchLockEnterPasscodeViewController *enterPasscodeViewController = [self enterPasscodeViewController]; @@ -231,8 +231,6 @@ - (void)lock UIViewController *displayViewController = [self transformViewController:enterPasscodeViewController byEmbedding:shouldEmbedInNavigationController]; - self.locked = YES; - if (fromBackground && self.appSwitchViewClass != NULL) { UIView *snapshotView = [[self.appSwitchViewClass alloc] init]; [self showSnapshotView:snapshotView]; @@ -292,8 +290,10 @@ - (void)applicationWillEnterForeground:(NSNotification *)notification dispatch_async(dispatch_get_main_queue(), ^{ [self.snapshotView removeFromSuperview]; self.snapshotView = nil; + if (self.locked && self.splashViewControllerClass == NULL && [self shouldUseTouchID]) { + [self showTouchID]; + } }); - } @@ -313,7 +313,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N } } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(locked))]) { BOOL locked = ((VENTouchLock *)object).locked; - if (locked && self.options.shouldBlurWhenLocked) { + if (locked && self.options.shouldBlurWhenLocked && !self.obscureView) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; UIView *topMostView = [UIViewController ventouchlock_topMostController].view; VENTouchLockBlurView *obscureView = [[VENTouchLockBlurView alloc] initWithFrame:topMostView.bounds blurEffectStyle:self.options.blurEffectStyle];