diff --git a/.travis.yml b/.travis.yml index fc77326..698bf9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: objective-c +osx_image: xcode7 script: - xctool -workspace VENTouchLock.xcworkspace -scheme VENTouchLockTests -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO - xcodebuild test -workspace VENTouchLock.xcworkspace -scheme VENTouchLockTests -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO diff --git a/VENTouchLock/Controllers/VENTouchLockSplashViewController.h b/VENTouchLock/Controllers/VENTouchLockSplashViewController.h index 9266ee0..f48b471 100644 --- a/VENTouchLock/Controllers/VENTouchLockSplashViewController.h +++ b/VENTouchLock/Controllers/VENTouchLockSplashViewController.h @@ -47,10 +47,5 @@ typedef NS_ENUM(NSUInteger, VENTouchLockSplashViewControllerUnlockType) { - (void)dismissWithUnlockSuccess:(BOOL)success unlockType:(VENTouchLockSplashViewControllerUnlockType)unlockType animated:(BOOL)animated; -/** - Signals the splash view controller to behave like a snapshot view for app-switch. This method should not be called outside of the VENTouchLock framework. - @param isSnapshotViewController YES if the splash view controller is for the app-switch snapshot. NO othwerise. - */ -- (void)setIsSnapshotViewController:(BOOL)isSnapshotViewController; @end diff --git a/VENTouchLock/Controllers/VENTouchLockSplashViewController.m b/VENTouchLock/Controllers/VENTouchLockSplashViewController.m index 7b6c1ac..1cf6a2a 100644 --- a/VENTouchLock/Controllers/VENTouchLockSplashViewController.m +++ b/VENTouchLock/Controllers/VENTouchLockSplashViewController.m @@ -2,10 +2,6 @@ #import "VENTouchLockEnterPasscodeViewController.h" #import "VENTouchLock.h" -@interface VENTouchLockSplashViewController () -@property (nonatomic, assign) BOOL isSnapshotViewController; -@end - @implementation VENTouchLockSplashViewController #pragma mark - Creation and Lifecycle @@ -13,9 +9,6 @@ @implementation VENTouchLockSplashViewController - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - if (!self.isSnapshotViewController) { - self.touchLock.backgroundLockVisible = NO; - } } - (instancetype)init @@ -49,25 +42,11 @@ - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - if (!self.isSnapshotViewController) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self showUnlockAnimated:NO]; - }); + if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) { + [self showUnlock]; } } -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; -} - -- (void)viewDidDisappear:(BOOL)animated -{ - [super viewDidDisappear:animated]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; -} - #pragma mark - Present unlock methods @@ -125,13 +104,6 @@ - (VENTouchLockEnterPasscodeViewController *)enterPasscodeVC return enterPasscodeVC; } -- (void)appWillEnterForeground -{ - if (!self.presentedViewController) { - [self showUnlockAnimated:NO]; - } -} - - (void)unlockWithType:(VENTouchLockSplashViewControllerUnlockType)unlockType { [self dismissWithUnlockSuccess:YES @@ -143,16 +115,23 @@ - (void)dismissWithUnlockSuccess:(BOOL)success unlockType:(VENTouchLockSplashViewControllerUnlockType)unlockType animated:(BOOL)animated { - [self.presentingViewController dismissViewControllerAnimated:animated completion:^{ - if (self.didFinishWithSuccess) { - self.didFinishWithSuccess(success, unlockType); - } - }]; + [self.touchLock unlockAnimated:animated]; + if (self.didFinishWithSuccess) { + self.didFinishWithSuccess(success, unlockType); + } } - (void)initialize { _touchLock = [VENTouchLock sharedInstance]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showUnlock) name:UIApplicationWillEnterForegroundNotification object:nil]; +} + +- (void)showUnlock +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [self showUnlockAnimated:NO]; + }); } @end \ No newline at end of file diff --git a/VENTouchLock/VENTouchLock.h b/VENTouchLock/VENTouchLock.h index 642ee90..0c0f560 100644 --- a/VENTouchLock/VENTouchLock.h +++ b/VENTouchLock/VENTouchLock.h @@ -14,10 +14,7 @@ typedef NS_ENUM(NSUInteger, VENTouchLockTouchIDResponse) { @interface VENTouchLock : NSObject -/** - YES if the app is locked after having entered the background, and NO otherwise. - */ -@property (assign, nonatomic) BOOL backgroundLockVisible; +@property (assign, nonatomic, getter=isPasscodePresented) BOOL passcodePresented; /** @return A singleton VENTouchLock instance. @@ -99,6 +96,12 @@ typedef NS_ENUM(NSUInteger, VENTouchLockTouchIDResponse) { */ - (void)lock; +/** + If the passcode screen is presented, calling this method will unlock it. + @param animated Whether or not the unlocking should animate. + */ +- (void)unlockAnimated:(BOOL)animated; + /** @return The proxy for the receiver's user interface. Custom appearance preferences may optionally be set by editing the returned instance's properties. */ diff --git a/VENTouchLock/VENTouchLock.m b/VENTouchLock/VENTouchLock.m index a6272e8..4dfb2c2 100644 --- a/VENTouchLock/VENTouchLock.m +++ b/VENTouchLock/VENTouchLock.m @@ -13,9 +13,13 @@ @interface VENTouchLock () @property (copy, nonatomic) NSString *touchIDReason; @property (assign, nonatomic) NSUInteger passcodeAttemptLimit; @property (assign, nonatomic) Class splashViewControllerClass; -@property (strong, nonatomic) UIView *snapshotView; @property (strong, nonatomic) VENTouchLockAppearance *appearance; +@property (strong, nonatomic) UIViewController *displayController; + +@property (weak, nonatomic) UIWindow *mainWindow; +@property (strong, nonatomic) UIWindow *lockWindow; + @end @implementation VENTouchLock @@ -41,9 +45,11 @@ - (instancetype)init self = [super init]; if (self) { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [notificationCenter addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; - [notificationCenter addObserver:self selector:@selector(applicationDidFinishLaunching:) name:UIApplicationDidFinishLaunchingNotification object:nil]; + + [notificationCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; + [notificationCenter addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; + + self.mainWindow = [[UIApplication sharedApplication].windows firstObject]; } return self; } @@ -62,6 +68,11 @@ - (void)setKeychainService:(NSString *)service self.splashViewControllerClass = splashViewControllerClass; } +- (BOOL)isPasscodePresented +{ + return self.lockWindow.isKeyWindow; +} + #pragma mark - Keychain Methods @@ -91,6 +102,8 @@ - (void)setPasscode:(NSString *)passcode - (void)deletePasscode { + [self unlockAnimated:NO]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:VENTouchLockUserDefaultsKeyTouchIDActivated]; [VENTouchLockEnterPasscodeViewController resetPasscodeAttemptHistory]; [[NSUserDefaults standardUserDefaults] synchronize]; @@ -174,71 +187,60 @@ - (void)requestTouchIDWithCompletion:(void (^)(VENTouchLockTouchIDResponse))comp - (void)lock { - if (![self isPasscodeSet]) { + if (![self isPasscodeSet] || self.isPasscodePresented) { return; } if (self.splashViewControllerClass != NULL) { VENTouchLockSplashViewController *splashViewController = [[self.splashViewControllerClass alloc] init]; if ([splashViewController isKindOfClass:[VENTouchLockSplashViewController class]]) { - UIWindow *mainWindow = [[UIApplication sharedApplication].windows firstObject]; - UIViewController *rootViewController = [UIViewController ventouchlock_topMostController]; - UIViewController *displayController; + self.lockWindow = [[UIWindow alloc] initWithFrame:self.mainWindow.frame]; + self.lockWindow.windowLevel = UIWindowLevelAlert + 1; + if (self.appearance.splashShouldEmbedInNavigationController) { - displayController = [splashViewController ventouchlock_embeddedInNavigationControllerWithNavigationBarClass:self.appearance.navigationBarClass]; + self.displayController = [splashViewController ventouchlock_embeddedInNavigationControllerWithNavigationBarClass:self.appearance.navigationBarClass]; } else { - displayController = splashViewController; + self.displayController = splashViewController; } - BOOL fromBackground = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; - if (fromBackground) { - [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - VENTouchLockSplashViewController *snapshotSplashViewController = [[self.splashViewControllerClass alloc] init]; - [snapshotSplashViewController setIsSnapshotViewController:YES]; - UIViewController *snapshotDisplayController; - if (self.appearance.splashShouldEmbedInNavigationController) { - snapshotDisplayController = [snapshotSplashViewController ventouchlock_embeddedInNavigationControllerWithNavigationBarClass:self.appearance.navigationBarClass]; - } - else { - snapshotDisplayController = snapshotSplashViewController; - } - [snapshotDisplayController loadView]; - [snapshotDisplayController viewDidLoad]; - snapshotDisplayController.view.frame = mainWindow.bounds; - self.snapshotView = snapshotDisplayController.view; - [mainWindow addSubview:self.snapshotView]; - } + self.lockWindow.rootViewController = self.displayController; + dispatch_async(dispatch_get_main_queue(), ^{ - self.backgroundLockVisible = YES; - [rootViewController presentViewController:displayController animated:NO completion:nil]; + [self.lockWindow makeKeyAndVisible]; }); } } } +- (void)unlockAnimated:(BOOL)animated +{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (animated) { + [UIView animateWithDuration:0.2 animations:^{ + self.lockWindow.alpha = 0; + } completion:^(BOOL finished) { + self.lockWindow.hidden = YES; + [self.mainWindow makeKeyAndVisible]; + }]; + } else { + self.lockWindow.hidden = YES; + [self.mainWindow makeKeyAndVisible]; + } + }); +} + #pragma mark - NSNotifications -- (void)applicationDidFinishLaunching:(NSNotification *)notification +- (void)applicationDidBecomeActive:(NSNotification *)notification { [self lock]; } -- (void)applicationDidEnterBackground:(NSNotification *)notification -{ - if (!self.backgroundLockVisible) { - [self lock]; - } -} - -- (void)applicationWillEnterForeground:(NSNotification *)notification +- (void)applicationWillResignActive:(NSNotification *)notification { - dispatch_async(dispatch_get_main_queue(), ^{ - [self.snapshotView removeFromSuperview]; - self.snapshotView = nil; - }); - + [self lock]; } @end diff --git a/VENTouchLockSample/Podfile.lock b/VENTouchLockSample/Podfile.lock index d3151ce..dddd121 100644 --- a/VENTouchLockSample/Podfile.lock +++ b/VENTouchLockSample/Podfile.lock @@ -1,7 +1,7 @@ PODS: - - KIF (3.2.2): - - KIF/XCTest (= 3.2.2) - - KIF/XCTest (3.2.2) + - KIF (3.3.0): + - KIF/Core (= 3.3.0) + - KIF/Core (3.3.0) - SSKeychain (1.2.2) DEPENDENCIES: @@ -9,7 +9,7 @@ DEPENDENCIES: - SSKeychain (~> 1.2.2) SPEC CHECKSUMS: - KIF: b0bd762b0c7890b04920cf618021d6d4fd5127bd + KIF: 0a82046d06f3648799cac522d2d0f7934214caac SSKeychain: 88767e903ee8d274ed380e364d96b7a101235286 -COCOAPODS: 0.37.2 +COCOAPODS: 0.38.2 diff --git a/VENTouchLockSample/VENTouchLockSampleTests/VENTouchLockAutoLockTests.m b/VENTouchLockSample/VENTouchLockSampleTests/VENTouchLockAutoLockTests.m index 440ee56..f5ca742 100644 --- a/VENTouchLockSample/VENTouchLockSampleTests/VENTouchLockAutoLockTests.m +++ b/VENTouchLockSample/VENTouchLockSampleTests/VENTouchLockAutoLockTests.m @@ -140,15 +140,7 @@ - (void)performPasscodeAttemptLimitTestWithSplashInNavVC:(BOOL)splashEmbeddedInN - (void)dismissAndResetLock { - UIViewController *viewController = [UIApplication sharedApplication].keyWindow.rootViewController; - while (viewController.presentedViewController) { - viewController = viewController.presentedViewController; - if ([viewController isKindOfClass:[VENTouchLockSplashViewController class]]) { - VENTouchLockSplashViewController *splashViewController = (VENTouchLockSplashViewController *)viewController; - [splashViewController dismissWithUnlockSuccess:YES unlockType:VENTouchLockSplashViewControllerUnlockTypePasscode animated:NO]; - } - } - [VENTouchLock sharedInstance].backgroundLockVisible = NO; + [[VENTouchLock sharedInstance] unlockAnimated:NO]; [[VENTouchLock sharedInstance] deletePasscode]; } @@ -162,6 +154,7 @@ - (void)simulateAppBackgroundThenForeground [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillEnterForegroundNotification object:nil]; [tester waitForTimeInterval:0.5]; [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil]; + [tester waitForTimeInterval:0.5]; } @end \ No newline at end of file