From 958b32265d6f450fc11f884fb839079721363ca8 Mon Sep 17 00:00:00 2001 From: Roland Leth Date: Mon, 24 Oct 2016 22:02:39 +0300 Subject: [PATCH] Callback for enabling passcode Added `enablePasscodeWhenApplicationEntersBackground`. It does the opposite of `disablePasscodeWhenApplicationEntersBackground`. --- CHANGELOG.md | 8 +++ .../LTHDemoViewController.m | 4 ++ LTHPasscodeViewController/LTHKeychainUtils.m | 4 +- .../LTHPasscodeViewController.h | 12 ++++- .../LTHPasscodeViewController.m | 54 ++++++++++++------- 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b56a420..ea4cbb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# 3.7.10 +* New delegate method: `passcodeWasEnabled`. Called when the passcode was enabled (Closed [#156](https://github.com/rolandleth/LTHPasscodeViewController/issues/156)). +* New method: `enablePasscodeWhenApplicationEntersBackground`. It reverts what `disablePasscodeWhenApplicationEntersBackground` does: it adds observers for `UIApplicationDidEnterBackgroundNotification` and `UIApplicationWillEnterForegroundNotification` (Closed [#158](https://github.com/rolandleth/LTHPasscodeViewController/issues/158)). + +# 3.7.9 +* Keychain leaks fixed. +* Back button fixed, it now properly resets state. + # 3.7.8 * Improved keyboard handling when displaying the lockscreen for the first time with TouchID enabled. * Fixed the bug where the keyboard was invisible after canceling the TouchID alert. diff --git a/Demo/LTHPasscodeViewController Demo/LTHDemoViewController.m b/Demo/LTHPasscodeViewController Demo/LTHDemoViewController.m index 2864366..669c10c 100644 --- a/Demo/LTHPasscodeViewController Demo/LTHDemoViewController.m +++ b/Demo/LTHPasscodeViewController Demo/LTHDemoViewController.m @@ -201,5 +201,9 @@ - (void)logoutButtonWasPressed { NSLog(@"Logout Button Was Pressed"); } +- (void)passcodeWasEnabled { + NSLog(@"Passcode Was Enabled"); +} + @end diff --git a/LTHPasscodeViewController/LTHKeychainUtils.m b/LTHPasscodeViewController/LTHKeychainUtils.m index 7fa8d3e..0297f0d 100644 --- a/LTHPasscodeViewController/LTHKeychainUtils.m +++ b/LTHPasscodeViewController/LTHKeychainUtils.m @@ -73,7 +73,7 @@ + (NSString *)getPasswordForUsername:(NSString *)username andServiceName:(NSStri CFTypeRef attrResult = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) attributeQuery, - &attrResult); + (CFTypeRef *) &attrResult); if (attrResult) CFRelease(attrResult); if (status != noErr) { @@ -95,7 +95,7 @@ + (NSString *)getPasswordForUsername:(NSString *)username andServiceName:(NSStri CFTypeRef resData = NULL; status = SecItemCopyMatching((__bridge CFDictionaryRef) passwordQuery, - &resData); + (CFTypeRef *) &resData); NSData *resultData = (__bridge_transfer NSData *)resData; if (status != noErr) { diff --git a/LTHPasscodeViewController/LTHPasscodeViewController.h b/LTHPasscodeViewController/LTHPasscodeViewController.h index acca12a..233963d 100755 --- a/LTHPasscodeViewController/LTHPasscodeViewController.h +++ b/LTHPasscodeViewController/LTHPasscodeViewController.h @@ -22,6 +22,10 @@ @brief Called when the passcode was entered successfully. */ - (void)passcodeWasEnteredSuccessfully; +/** + @brief Called when the passcode was enabled. + */ +- (void)passcodeWasEnabled; /** @brief Called when the logout button was pressed. */ @@ -323,9 +327,13 @@ */ - (void)setIsSimple:(BOOL)isSimple inViewController:(UIViewController *)viewController asModal:(BOOL)isModal; /** - @brief The passcode view will be shown by default when entering the app from background. This method disables this behavior by removing the observer for UIApplicationDidEnterBackgroundNotification and UIApplicationWillEnterForegroundNotification. + @brief The passcode view will be shown by default when entering the app from background. This method disables this behavior by removing the observers for UIApplicationDidEnterBackgroundNotification and UIApplicationWillEnterForegroundNotification. */ - (void)disablePasscodeWhenApplicationEntersBackground; +/** + @brief The passcode view will be shown by default when entering the app from background. `disablePasscodeWhenApplicationEntersBackground` can disable that behavior and this method enables it again, by adding back the observers for UIApplicationDidEnterBackgroundNotification and UIApplicationWillEnterForegroundNotification + */ +- (void)enablePasscodeWhenApplicationEntersBackground; /** @brief Returns a Boolean value that indicates whether a passcode exists (@c YES) or not (@c NO). @return @c YES if a passcode is enabled. This also means it is enabled, unless custom logic was added to the library. @@ -378,4 +386,4 @@ */ + (instancetype)sharedUser; -@end \ No newline at end of file +@end diff --git a/LTHPasscodeViewController/LTHPasscodeViewController.m b/LTHPasscodeViewController/LTHPasscodeViewController.m index fa211e9..66cba38 100755 --- a/LTHPasscodeViewController/LTHPasscodeViewController.m +++ b/LTHPasscodeViewController/LTHPasscodeViewController.m @@ -71,6 +71,7 @@ @interface LTHPasscodeViewController () @property (nonatomic, assign) CGFloat iPadFontSizeModifier; @property (nonatomic, assign) CGFloat iPhoneHorizontalGap; +@property (nonatomic, assign) BOOL passcodeAlreadyExists; @property (nonatomic, assign) BOOL usesKeychain; @property (nonatomic, assign) BOOL displayedAsModal; @property (nonatomic, assign) BOOL displayedAsLockScreen; @@ -258,6 +259,13 @@ - (void)_deletePasscode { - (void)_savePasscode:(NSString *)passcode { + if (!_passcodeAlreadyExists && + [self.delegate respondsToSelector:@selector(passcodeWasEnabled)]) { + [self.delegate passcodeWasEnabled]; + } + + _passcodeAlreadyExists = YES; + if (!_usesKeychain && [self.delegate respondsToSelector:@selector(savePasscode:)]) { [self.delegate savePasscode:passcode]; @@ -487,10 +495,7 @@ - (void)_cancelAndDismissMe { if ([self.delegate respondsToSelector: @selector(passcodeViewControllerWillClose)]) { [self.delegate performSelector: @selector(passcodeViewControllerWillClose)]; } - // Or, if you prefer by notifications: - // [[NSNotificationCenter defaultCenter] postNotificationName: @"passcodeViewControllerWillClose" - // object: self - // userInfo: nil]; + if (_displayedAsModal) [self dismissViewControllerAnimated:YES completion:nil]; else if (!_displayedAsLockScreen) [self.navigationController popViewControllerAnimated:YES]; } @@ -542,10 +547,7 @@ - (void)_dismissMe { if ([self.delegate respondsToSelector: @selector(passcodeViewControllerWillClose)]) { [self.delegate performSelector: @selector(passcodeViewControllerWillClose)]; } - // Or, if you prefer by notifications: - // [[NSNotificationCenter defaultCenter] postNotificationName: @"passcodeViewControllerWillClose" - // object: self - // userInfo: nil]; + if (_displayedAsLockScreen) { [self.view removeFromSuperview]; [self removeFromParentViewController]; @@ -1048,6 +1050,7 @@ - (void)_prepareNavigationControllerWithController:(UIViewController *)viewContr - (void)showForEnablingPasscodeInViewController:(UIViewController *)viewController asModal:(BOOL)isModal { _displayedAsModal = isModal; + _passcodeAlreadyExists = NO; [self _prepareForEnablingPasscode]; [self _prepareNavigationControllerWithController:viewController]; self.title = LTHPasscodeViewControllerStrings(self.enablePasscodeString); @@ -1222,10 +1225,6 @@ - (BOOL)_validatePasscode:(NSString *)typedString { // App launch/Turning passcode off: Passcode OK -> dismiss, Passcode incorrect -> deny access. else { if ([typedString isEqualToString: savedPasscode]) { - // Or, if you prefer by notifications: - // [[NSNotificationCenter defaultCenter] postNotificationName: @"passcodeWasEnteredSuccessfully" - // object: self - // userInfo: nil]; [self _dismissMe]; _useFallbackPasscode = NO; if ([self.delegate respondsToSelector: @selector(passcodeWasEnteredSuccessfully)]) { @@ -1320,10 +1319,6 @@ - (void)_denyAccess { [self.delegate respondsToSelector: @selector(maxNumberOfFailedAttemptsReached)]) { [self.delegate maxNumberOfFailedAttemptsReached]; } - // Or, if you prefer by notifications: - // [[NSNotificationCenter defaultCenter] postNotificationName: @"maxNumberOfFailedAttemptsReached" - // object: self - // userInfo: nil]; if (_failedAttempts == 1) { _failedAttemptLabel.text = @@ -1583,6 +1578,7 @@ - (void)_loadMiscDefaults { _displayedAsModal = YES; _hidesBackButton = YES; _hidesCancelButton = YES; + _passcodeAlreadyExists = YES; #if !(TARGET_IPHONE_SIMULATOR) _allowUnlockWithTouchID = [self _allowUnlockWithTouchID]; #else @@ -1771,8 +1767,30 @@ - (void)setIfNotEqualTransform:(CGAffineTransform)transform frame:(CGRect)frame } - (void)disablePasscodeWhenApplicationEntersBackground { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] + removeObserver:self + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + removeObserver:self + name:UIApplicationWillEnterForegroundNotification + object:nil]; +} + +- (void)enablePasscodeWhenApplicationEntersBackground { + // To avoid double registering. + [self disablePasscodeWhenApplicationEntersBackground]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(_applicationDidEnterBackground) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(_applicationWillEnterForeground) + name:UIApplicationWillEnterForegroundNotification + object:nil]; }