From fdf98ba6447ebe09c149a88aab45df5dee680dec Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Mon, 5 Jun 2017 23:07:43 +0300 Subject: [PATCH 01/32] Swift 3.0 updates --- PasscodeLock.xcodeproj/project.pbxproj | 3 +++ PasscodeLockDemo/PasscodeLockConfiguration.swift | 2 ++ PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/PasscodeLock.xcodeproj/project.pbxproj b/PasscodeLock.xcodeproj/project.pbxproj index fe6032d9..7a05fabb 100644 --- a/PasscodeLock.xcodeproj/project.pbxproj +++ b/PasscodeLock.xcodeproj/project.pbxproj @@ -461,6 +461,7 @@ }; C99EAF481B90B05700D61E1B = { CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 0830; }; C9D3DF0F1B91AD11008561EB = { CreatedOnToolsVersion = 7.0; @@ -816,6 +817,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PasscodeLockTests/PasscodeLockTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -828,6 +830,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PasscodeLockTests/PasscodeLockTests-Bridging-Header.h"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/PasscodeLockDemo/PasscodeLockConfiguration.swift b/PasscodeLockDemo/PasscodeLockConfiguration.swift index 5a176bd7..4dfed315 100644 --- a/PasscodeLockDemo/PasscodeLockConfiguration.swift +++ b/PasscodeLockDemo/PasscodeLockConfiguration.swift @@ -10,6 +10,8 @@ import Foundation import PasscodeLock struct PasscodeLockConfiguration: PasscodeLockConfigurationType { + var touchIdReason: String? + let repository: PasscodeRepositoryType let passcodeLength = 4 diff --git a/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift b/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift index 2e4dcf94..87095ff5 100644 --- a/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift +++ b/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift @@ -15,9 +15,9 @@ class NotificaionObserver: NSObject { func observe(notification: String) { - let center = NSNotificationCenter.defaultCenter() + let center = NotificationCenter.default - center.addObserver(self, selector: "handle:", name: notification, object: nil) + center.addObserver(self, selector: "handle:", name: NSNotification.Name(rawValue: notification), object: nil) } func handle(notification: NSNotification) { From baa6cc39613e372ea0dea653e92fda66a8025aae Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:07:19 +0300 Subject: [PATCH 02/32] Add new state .optionalEnterPassword .optionalEnterPassword is same as .enterPassword but with cancellation possibility. --- PasscodeLock.xcodeproj/project.pbxproj | 4 + .../EnterOptionalPasscodeState.swift | 74 +++++++++++++++++++ PasscodeLock/PasscodeLockViewController.swift | 33 ++++++++- 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 PasscodeLock/PasscodeLock/EnterOptionalPasscodeState.swift diff --git a/PasscodeLock.xcodeproj/project.pbxproj b/PasscodeLock.xcodeproj/project.pbxproj index 7a05fabb..1993f8a3 100644 --- a/PasscodeLock.xcodeproj/project.pbxproj +++ b/PasscodeLock.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 6E93C8EC1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E93C8EB1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift */; }; C99EAF431B90B05700D61E1B /* PasscodeLock.h in Headers */ = {isa = PBXBuildFile; fileRef = C99EAF421B90B05700D61E1B /* PasscodeLock.h */; settings = {ATTRIBUTES = (Public, ); }; }; C99EAF4A1B90B05800D61E1B /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C99EAF3F1B90B05700D61E1B /* PasscodeLock.framework */; }; C9D3DF0B1B919CE4008561EB /* PasscodeLockView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C9D3DF0A1B919CE4008561EB /* PasscodeLockView.xib */; }; @@ -106,6 +107,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 6E93C8EB1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnterOptionalPasscodeState.swift; sourceTree = ""; }; C99EAF3F1B90B05700D61E1B /* PasscodeLock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PasscodeLock.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C99EAF421B90B05700D61E1B /* PasscodeLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasscodeLock.h; sourceTree = ""; }; C99EAF441B90B05700D61E1B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -288,6 +290,7 @@ children = ( C9DC07E01B90BBFD007A4DD0 /* PasscodeLock.swift */, C9DC07F11B90C9DE007A4DD0 /* EnterPasscodeState.swift */, + 6E93C8EB1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift */, C9DC07FE1B90D24A007A4DD0 /* SetPasscodeState.swift */, C9DC08011B90D2BA007A4DD0 /* ConfirmPasscodeState.swift */, C9DC08041B90D394007A4DD0 /* ChangePasscodeState.swift */, @@ -557,6 +560,7 @@ C9DC07F21B90C9DE007A4DD0 /* EnterPasscodeState.swift in Sources */, C9DC08141B90DE50007A4DD0 /* PasscodeSignButton.swift in Sources */, C9D3DF481B91F099008561EB /* PasscodeLockPresenter.swift in Sources */, + 6E93C8EC1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift in Sources */, C9DC07D81B90B261007A4DD0 /* PasscodeLockStateType.swift in Sources */, C9DC08161B90DF4E007A4DD0 /* PasscodeLockViewController.swift in Sources */, C9DC07E11B90BBFD007A4DD0 /* PasscodeLock.swift in Sources */, diff --git a/PasscodeLock/PasscodeLock/EnterOptionalPasscodeState.swift b/PasscodeLock/PasscodeLock/EnterOptionalPasscodeState.swift new file mode 100644 index 00000000..a58ea272 --- /dev/null +++ b/PasscodeLock/PasscodeLock/EnterOptionalPasscodeState.swift @@ -0,0 +1,74 @@ +// +// EnterOptionalPasscodeState.swift +// PasscodeLock +// +// Created by Yanko Dimitrov on 8/28/15. +// Copyright © 2015 Yanko Dimitrov. All rights reserved. +// + +import Foundation + +struct EnterOptionalPasscodeState: PasscodeLockStateType { + + let title: String + let description: String + let isCancellableAction: Bool + var isTouchIDAllowed = true + + static let incorrectPasscodeAttemptsKey = "incorrectPasscodeAttempts" + static var incorrectPasscodeAttempts: Int { + get { + return UserDefaults.standard.integer(forKey: incorrectPasscodeAttemptsKey) + } + set { + UserDefaults.standard.set(newValue, forKey: incorrectPasscodeAttemptsKey) + } + } + + private var isNotificationSent = false + + init(allowCancellation: Bool = true) { + + isCancellableAction = allowCancellation + title = localizedStringFor("PasscodeLockEnterTitle", comment: "Enter passcode title") + description = localizedStringFor("PasscodeLockEnterDescription", comment: "Enter passcode description") + } + + mutating func acceptPasscode(_ passcode: [String], fromLock lock: PasscodeLockType) { + + guard let currentPasscode = lock.repository.passcode else { + return + } + + var incorrectPasscodeAttempts = EnterPasscodeState.incorrectPasscodeAttempts + if passcode == currentPasscode { + + lock.delegate?.passcodeLockDidSucceed(lock) + incorrectPasscodeAttempts = 0 + } else { + + incorrectPasscodeAttempts += 1 + + if incorrectPasscodeAttempts >= lock.configuration.maximumInccorectPasscodeAttempts { + + postNotification() + incorrectPasscodeAttempts = 0 + } + + lock.delegate?.passcodeLockDidFail(lock) + } + + EnterPasscodeState.incorrectPasscodeAttempts = incorrectPasscodeAttempts + } + + fileprivate mutating func postNotification() { + + guard !isNotificationSent else { return } + + let center = NotificationCenter.default + + center.post(name: Notification.Name(rawValue: PasscodeLockIncorrectPasscodeNotification), object: nil) + + isNotificationSent = true + } +} diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index a14a58fa..1eed5771 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -12,6 +12,7 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat public enum LockState { case enterPasscode + case enterOptionalPasscode case setPasscode case changePasscode case removePasscode @@ -20,6 +21,7 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat switch self { case .enterPasscode: return EnterPasscodeState() + case .enterOptionalPasscode: return EnterOptionalPasscodeState() case .setPasscode: return SetPasscodeState() case .changePasscode: return ChangePasscodeState() case .removePasscode: return EnterPasscodeState(allowCancellation: true) @@ -37,12 +39,16 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat open var successCallback: ((_ lock: PasscodeLockType) -> Void)? open var dismissCompletionCallback: (()->Void)? + open var cancelCompletionCallback: (()->Void)? + open var wrongPasswordCallback: ((_ attemptNo: Int) -> Void)? + open var tooManyAttemptsCallback: ((_ attemptNo: Int)->Void)? open var animateOnDismiss: Bool open var notificationCenter: NotificationCenter? internal let passcodeConfiguration: PasscodeLockConfigurationType internal var passcodeLock: PasscodeLockType internal var isPlaceholdersAnimationCompleted = true + internal var extraCallbacks = false fileprivate var shouldTryToAuthenticateWithBiometrics = true @@ -66,6 +72,9 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat public convenience init(state: LockState, configuration: PasscodeLockConfigurationType, animateOnDismiss: Bool = true) { self.init(state: state.getState(), configuration: configuration, animateOnDismiss: animateOnDismiss) + + self.extraCallbacks = ( state == .enterPasscode || state == .enterOptionalPasscode ) + } public required init(coder aDecoder: NSCoder) { @@ -107,7 +116,7 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat titleLabel?.text = passcodeLock.state.title descriptionLabel?.text = passcodeLock.state.description cancelButton?.isHidden = !passcodeLock.state.isCancellableAction - touchIDButton?.isHidden = !passcodeLock.isTouchIDAllowed + touchIDButton?.isHidden = !passcodeLock.isTouchIDAllowed || passcodeLock.configuration.shouldDisableTouchIDButton } // MARK: - Events @@ -147,7 +156,9 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat @IBAction func cancelButtonTap(_ sender: UIButton) { - dismissPasscodeLock(passcodeLock) + dismissPasscodeLock(passcodeLock, completionHandler: { [weak self] _ in + self?.cancelCompletionCallback?() + }) } @IBAction func deleteSignButtonTap(_ sender: UIButton) { @@ -254,6 +265,24 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat open func passcodeLockDidFail(_ lock: PasscodeLockType) { animateWrongPassword() + + if ( self.extraCallbacks ) { + let attemptNo = EnterPasscodeState.incorrectPasscodeAttempts + 1 + let maxAttempts = lock.configuration.maximumInccorectPasscodeAttempts + let shouldDissmissOnTooManyAttempts = lock.configuration.shouldDismissOnTooManyAttempts && lock.state.isCancellableAction + + if (( maxAttempts >= 0) && ( attemptNo >= maxAttempts )) { + if ( shouldDissmissOnTooManyAttempts ) { + dismissPasscodeLock(lock, completionHandler: { [weak self] _ in + self?.tooManyAttemptsCallback?(attemptNo) + }) + } else { + self.tooManyAttemptsCallback?(attemptNo) + } + } else { + self.wrongPasswordCallback?(attemptNo) + } + } } open func passcodeLockDidChangeState(_ lock: PasscodeLockType) { From 075cd2aa69a0ee0a56a02eef621d6ac819b003d4 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:09:59 +0300 Subject: [PATCH 03/32] Add new options - Possibility to hide touchID button from view. - Possibility to dismiss view automatically on too many wrong attempts. Requires state with possibility to cancel. --- PasscodeLock/Protocols/PasscodeLockConfigurationType.swift | 2 ++ PasscodeLockDemo/PasscodeLockConfiguration.swift | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift b/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift index ec158e75..f0aa2593 100644 --- a/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift +++ b/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift @@ -14,6 +14,8 @@ public protocol PasscodeLockConfigurationType { var passcodeLength: Int {get} var isTouchIDAllowed: Bool {get set} var shouldRequestTouchIDImmediately: Bool {get} + var shouldDisableTouchIDButton: Bool {get} var touchIdReason: String? {get set} var maximumInccorectPasscodeAttempts: Int {get} + var shouldDismissOnTooManyAttempts: Bool {get} } diff --git a/PasscodeLockDemo/PasscodeLockConfiguration.swift b/PasscodeLockDemo/PasscodeLockConfiguration.swift index 4dfed315..f399a6b3 100644 --- a/PasscodeLockDemo/PasscodeLockConfiguration.swift +++ b/PasscodeLockDemo/PasscodeLockConfiguration.swift @@ -10,6 +10,7 @@ import Foundation import PasscodeLock struct PasscodeLockConfiguration: PasscodeLockConfigurationType { + var touchIdReason: String? @@ -17,7 +18,10 @@ struct PasscodeLockConfiguration: PasscodeLockConfigurationType { let passcodeLength = 4 var isTouchIDAllowed = true let shouldRequestTouchIDImmediately = true - let maximumInccorectPasscodeAttempts = -1 + let shouldDisableTouchIDButton = true + let maximumInccorectPasscodeAttempts = 3 + // let maximumInccorectPasscodeAttempts = -1 + let shouldDismissOnTooManyAttempts = true init(repository: PasscodeRepositoryType) { From f1c3b24f4109662b67584a1edf8141131c2d6674 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:11:08 +0300 Subject: [PATCH 04/32] Update demo Use new features and add new button to test authentication manually. Also test new callbacks by logging. --- PasscodeLockDemo/Base.lproj/Main.storyboard | 38 +++++++++++++------ .../PasscodeSettingsViewController.swift | 29 ++++++++++++++ 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/PasscodeLockDemo/Base.lproj/Main.storyboard b/PasscodeLockDemo/Base.lproj/Main.storyboard index bea52e36..c51806b8 100644 --- a/PasscodeLockDemo/Base.lproj/Main.storyboard +++ b/PasscodeLockDemo/Base.lproj/Main.storyboard @@ -1,8 +1,12 @@ - - + + + + + - + + @@ -14,44 +18,44 @@ - + - + - + @@ -59,8 +63,15 @@ + - + @@ -69,6 +80,8 @@ + + @@ -81,6 +94,7 @@ + diff --git a/PasscodeLockDemo/PasscodeSettingsViewController.swift b/PasscodeLockDemo/PasscodeSettingsViewController.swift index 7eafbdff..e5301357 100644 --- a/PasscodeLockDemo/PasscodeSettingsViewController.swift +++ b/PasscodeLockDemo/PasscodeSettingsViewController.swift @@ -15,6 +15,7 @@ class PasscodeSettingsViewController: UIViewController { @IBOutlet weak var changePasscodeButton: UIButton! @IBOutlet weak var testTextField: UITextField! @IBOutlet weak var testActivityButton: UIButton! + @IBOutlet weak var authenticateNowButton: UIButton! fileprivate let configuration: PasscodeLockConfigurationType @@ -46,6 +47,7 @@ class PasscodeSettingsViewController: UIViewController { let hasPasscode = configuration.repository.hasPasscode changePasscodeButton.isHidden = !hasPasscode + authenticateNowButton.isHidden = !hasPasscode passcodeSwitch.isOn = hasPasscode } @@ -82,6 +84,33 @@ class PasscodeSettingsViewController: UIViewController { present(passcodeLock, animated: true, completion: nil) } + @IBAction func authenticateNowButtonTap(_ sender: UIButton) { + + let repo = UserDefaultsPasscodeRepository() + let config = PasscodeLockConfiguration(repository: repo) + + let passcodeLock = PasscodeLockViewController(state: .enterOptionalPasscode, configuration: config) + + passcodeLock.successCallback = { lock in + NSLog("Success") + } + + passcodeLock.cancelCompletionCallback = { _ in + NSLog("Cancelled") + } + + passcodeLock.wrongPasswordCallback = { attemptNo in + NSLog("Wrong password attempt no %d", attemptNo) + } + + passcodeLock.tooManyAttemptsCallback = { attemptNo in + NSLog("Maximum amount of %d attempts reached", attemptNo) + } + + present(passcodeLock, animated: true, completion: nil) + + } + @IBAction func testAlertButtonTap(_ sender: UIButton) { let alertVC = UIAlertController(title: "Test", message: "", preferredStyle: .alert) From 4b5d7d54ffa270f8c417444005d53b5b00a14fab Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:21:01 +0300 Subject: [PATCH 05/32] code beautifying --- PasscodeLockDemo/PasscodeLockConfiguration.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/PasscodeLockDemo/PasscodeLockConfiguration.swift b/PasscodeLockDemo/PasscodeLockConfiguration.swift index f399a6b3..082708d6 100644 --- a/PasscodeLockDemo/PasscodeLockConfiguration.swift +++ b/PasscodeLockDemo/PasscodeLockConfiguration.swift @@ -11,9 +11,7 @@ import PasscodeLock struct PasscodeLockConfiguration: PasscodeLockConfigurationType { - var touchIdReason: String? - - + var touchIdReason: String? let repository: PasscodeRepositoryType let passcodeLength = 4 var isTouchIDAllowed = true From 76d1093638810b3b4145d8100ed6a3cb3d07b555 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:21:12 +0300 Subject: [PATCH 06/32] Update podscpec --- PasscodeLock.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PasscodeLock.podspec b/PasscodeLock.podspec index 2df42467..78ce554a 100755 --- a/PasscodeLock.podspec +++ b/PasscodeLock.podspec @@ -3,9 +3,9 @@ s.name = 'PasscodeLock' s.version = '1.0.3' s.license = { :type => "MIT", :file => 'LICENSE.txt' } s.summary = 'An iOS passcode lock with Touch ID authentication written in Swift.' -s.homepage = 'https://github.com/velikanov/SwiftPasscodeLock' -s.authors = { 'Yanko Dimitrov' => '', 'Chris Ziogas' => '', } -s.source = { :git => 'https://github.com/velikanov/SwiftPasscodeLock.git' } +s.homepage = 'https://github.com/oskarirauta/SwiftPasscodeLock' +s.authors = { ‘Oskari Rauta’ => ‘’, ’Yanko Dimitrov' => '', 'Chris Ziogas' => '', } +s.source = { :git => 'https://github.com/oskarirauta/SwiftPasscodeLock.git' } s.ios.deployment_target = '8.0' From 8320ac4a79bf9565dd71d888ec95cf986cdc9389 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:21:20 +0300 Subject: [PATCH 07/32] Update Readme --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index de7300db..08c6cbef 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # PasscodeLock A Swift implementation of passcode lock for iOS with TouchID authentication. -Originally created by [@yankodimitrov](https://github.com/yankodimitrov/SwiftPasscodeLock), hope you're doing well. +Originally created by [@yankodimitrov](https://github.com/yankodimitrov/SwiftPasscodeLock), then forded by [@velikanov](https://github.com/velikanov/SwiftPasscodeLock) hope you're doing well. ## Installation -PasscodeLock requires Swift 2.0 and Xcode 7 +PasscodeLock requires Swift 3.0 and Xcode 8 ### [CocoaPods](http://cocoapods.org/) @@ -18,7 +18,7 @@ To integrate PasscodeLock into your Xcode project using CocoaPods, specify it in source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' -pod 'PasscodeLock', '~> 1.0.2' +pod 'PasscodeLock', '~> 1.0.3’ ``` Then, run the following command: @@ -31,7 +31,7 @@ $ pod install Add the following line to your [Cartfile](https://github.com/carthage/carthage) ```swift -github "velikanov/SwiftPasscodeLock" +github “oskarirauta/SwiftPasscodeLock" ``` ## Usage @@ -60,11 +60,14 @@ import UIKit import PasscodeLock class PasscodeLockConfiguration: PasscodeLockConfigurationType { + var touchIdReason: String? let repository: PasscodeRepositoryType var passcodeLength = 4 // Specify the required amount of passcode digits var isTouchIDAllowed = true // Enable Touch ID var shouldRequestTouchIDImmediately = true // Use Touch ID authentication immediately + var shouldDisableTouchIDButton = true // Hides manual touchID activation button from enter code view var maximumInccorectPasscodeAttempts = 3 // Maximum incorrect passcode attempts + var shouldDismissOnTooManyAttempts = true // When cancellation is available, dismiss code input view after too many wrong code attempts init(repository: PasscodeRepositoryType) { self.repository = repository @@ -87,7 +90,7 @@ let passcodeViewController = PasscodeLockViewController(state: .SetPasscode, con presentViewController(passcodeViewController, animated: true, completion: nil) ``` -You can present the `PasscodeLockViewController` in one of the four initial states using the `LockState` enumeration options: `.EnterPasscode`, `.SetPasscode`, `.ChangePasscode`, `.RemovePasscode`. +You can present the `PasscodeLockViewController` in one of the four initial states using the `LockState` enumeration options: `.enterPasscode`, `.enterOptionalPasscode`, `.setPasscode`, `.changePasscode`, `.removePasscode`. Also you can set the initial passcode lock state to your own implementation of the `PasscodeLockStateType` protocol. From 068aeb9aa8d08f7fc57f22a0db76fcf928e2c9f3 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:24:14 +0300 Subject: [PATCH 08/32] More updates to ReadME --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 08c6cbef..af472439 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ To integrate PasscodeLock into your Xcode project using CocoaPods, specify it in ```ruby source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, ‘8.0’ -pod 'PasscodeLock', '~> 1.0.3’ +pod 'PasscodeLock', :git => ‘https://github.com/oskarirauta/PasscodeLock.git' ``` Then, run the following command: From 58afd2d4770cc049218c41bcc28db803ca2d948e Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:30:30 +0300 Subject: [PATCH 09/32] Changes to demo Preparing for future changes --- PasscodeLockDemo/PasscodeSettingsViewController.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PasscodeLockDemo/PasscodeSettingsViewController.swift b/PasscodeLockDemo/PasscodeSettingsViewController.swift index e5301357..b9d7c5d5 100644 --- a/PasscodeLockDemo/PasscodeSettingsViewController.swift +++ b/PasscodeLockDemo/PasscodeSettingsViewController.swift @@ -71,6 +71,7 @@ class PasscodeSettingsViewController: UIViewController { } } + passcodeVC.modalPresentationStyle = .overCurrentContext present(passcodeVC, animated: true, completion: nil) } @@ -81,6 +82,7 @@ class PasscodeSettingsViewController: UIViewController { let passcodeLock = PasscodeLockViewController(state: .changePasscode, configuration: config) + passcodeLock.modalPresentationStyle = .overCurrentContext present(passcodeLock, animated: true, completion: nil) } @@ -107,6 +109,7 @@ class PasscodeSettingsViewController: UIViewController { NSLog("Maximum amount of %d attempts reached", attemptNo) } + passcodeLock.modalPresentationStyle = .overCurrentContext present(passcodeLock, animated: true, completion: nil) } From 89d77ba9bf4c2d9310b4c8c56cae514e0048861b Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:31:01 +0300 Subject: [PATCH 10/32] Update Readme Add list of possible callbacks --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index af472439..722d83be 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,15 @@ presentViewController(passcodeViewController, animated: true, completion: nil) You can present the `PasscodeLockViewController` in one of the four initial states using the `LockState` enumeration options: `.enterPasscode`, `.enterOptionalPasscode`, `.setPasscode`, `.changePasscode`, `.removePasscode`. +Following callbacks are available: +```swift + open var successCallback: ((_ lock: PasscodeLockType) -> Void)? + open var dismissCompletionCallback: (()->Void)? + open var cancelCompletionCallback: (()->Void)? + open var wrongPasswordCallback: ((_ attemptNo: Int) -> Void)? + open var tooManyAttemptsCallback: ((_ attemptNo: Int)->Void)? +``` + Also you can set the initial passcode lock state to your own implementation of the `PasscodeLockStateType` protocol. ## Customization From 87c5f8e99bf35f26c5c169b5d6ae7023701ddc9f Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:34:09 +0300 Subject: [PATCH 11/32] fix image in Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 722d83be..3d4aa718 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ The PasscodeLock will look for `PasscodeLockView.xib` inside your app bundle and Keep in mind that when using custom classes that are defined in another module, you'll need to set the Module field to that module's name in the Identity Inspector: - + Then connect the `view` outlet to the view of your `xib` file and make sure to conenct the remaining `IBOutlet`s and `IBAction`s. From 5376a04556bc545ecd05d1c0d5e1a931dfda41ad Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:35:15 +0300 Subject: [PATCH 12/32] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d4aa718..20026af9 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ The PasscodeLock will look for `PasscodeLockView.xib` inside your app bundle and Keep in mind that when using custom classes that are defined in another module, you'll need to set the Module field to that module's name in the Identity Inspector: - + Then connect the `view` outlet to the view of your `xib` file and make sure to conenct the remaining `IBOutlet`s and `IBAction`s. From 623430de560af91ac97c5872a104dc3cbc23197d Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 01:37:04 +0300 Subject: [PATCH 13/32] update Readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 20026af9..33e5254b 100644 --- a/README.md +++ b/README.md @@ -111,13 +111,13 @@ The PasscodeLock will look for `PasscodeLockView.xib` inside your app bundle and Keep in mind that when using custom classes that are defined in another module, you'll need to set the Module field to that module's name in the Identity Inspector: - + Then connect the `view` outlet to the view of your `xib` file and make sure to conenct the remaining `IBOutlet`s and `IBAction`s. PasscodeLock comes with two view components: `PasscodeSignPlaceholderView` and `PasscodeSignButton` that you can use to create your own custom designs. Both classes are `@IBDesignable` and `@IBInspectable`, so you can see their appearance and change their properties right inside the interface builder: - + ### Localization From eea6e1f0c1c6deff1fc3e891794d0537959fe5f9 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 22:25:26 +0300 Subject: [PATCH 14/32] add borderColor property --- .../Views/PasscodeSignPlaceholderView.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/PasscodeLock/Views/PasscodeSignPlaceholderView.swift b/PasscodeLock/Views/PasscodeSignPlaceholderView.swift index 2191a302..3794b9b2 100644 --- a/PasscodeLock/Views/PasscodeSignPlaceholderView.swift +++ b/PasscodeLock/Views/PasscodeSignPlaceholderView.swift @@ -38,6 +38,13 @@ open class PasscodeSignPlaceholderView: UIView { } } + @IBInspectable + open var borderColor: UIColor = UIColor.gray { + didSet { + setupView() + } + } + public override init(frame: CGRect) { super.init(frame: frame) @@ -59,15 +66,15 @@ open class PasscodeSignPlaceholderView: UIView { layer.cornerRadius = 8 layer.borderWidth = 1 - layer.borderColor = activeColor.cgColor + layer.borderColor = borderColor.cgColor backgroundColor = inactiveColor } fileprivate func colorsForState(_ state: State) -> (backgroundColor: UIColor, borderColor: UIColor) { switch state { - case .inactive: return (inactiveColor, activeColor) - case .active: return (activeColor, activeColor) + case .inactive: return (inactiveColor, borderColor) + case .active: return (activeColor, borderColor) case .error: return (errorColor, errorColor) } } From bebcd7c5ac742d665c856e641b80c5e83164c90f Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 22:27:07 +0300 Subject: [PATCH 15/32] xib updates --- PasscodeLock/Views/PasscodeLockView.xib | 203 ++++++++++++------------ 1 file changed, 102 insertions(+), 101 deletions(-) diff --git a/PasscodeLock/Views/PasscodeLockView.xib b/PasscodeLock/Views/PasscodeLockView.xib index c17dae99..5fde72c4 100644 --- a/PasscodeLock/Views/PasscodeLockView.xib +++ b/PasscodeLock/Views/PasscodeLockView.xib @@ -1,8 +1,12 @@ - - + + + + + - + + @@ -14,94 +18,94 @@ - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -116,23 +120,23 @@ - + From cfc5e943a29326f1dc64460f23707917870306fb Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 22:28:47 +0300 Subject: [PATCH 16/32] add darkUI variation --- PasscodeLock.xcodeproj/project.pbxproj | 4 + PasscodeLock/PasscodeLockViewController.swift | 15 +- PasscodeLock/Views/DarkPasscodeLockView.xib | 465 ++++++++++++++++++ 3 files changed, 480 insertions(+), 4 deletions(-) create mode 100644 PasscodeLock/Views/DarkPasscodeLockView.xib diff --git a/PasscodeLock.xcodeproj/project.pbxproj b/PasscodeLock.xcodeproj/project.pbxproj index 1993f8a3..f1d6bbf8 100644 --- a/PasscodeLock.xcodeproj/project.pbxproj +++ b/PasscodeLock.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 6E2B4C0E1EE72C68005D20D0 /* DarkPasscodeLockView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6E2B4C0D1EE72C68005D20D0 /* DarkPasscodeLockView.xib */; }; 6E93C8EC1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E93C8EB1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift */; }; C99EAF431B90B05700D61E1B /* PasscodeLock.h in Headers */ = {isa = PBXBuildFile; fileRef = C99EAF421B90B05700D61E1B /* PasscodeLock.h */; settings = {ATTRIBUTES = (Public, ); }; }; C99EAF4A1B90B05800D61E1B /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C99EAF3F1B90B05700D61E1B /* PasscodeLock.framework */; }; @@ -107,6 +108,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 6E2B4C0D1EE72C68005D20D0 /* DarkPasscodeLockView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DarkPasscodeLockView.xib; sourceTree = ""; }; 6E93C8EB1EE5FA5C00D4F2F3 /* EnterOptionalPasscodeState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnterOptionalPasscodeState.swift; sourceTree = ""; }; C99EAF3F1B90B05700D61E1B /* PasscodeLock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PasscodeLock.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C99EAF421B90B05700D61E1B /* PasscodeLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasscodeLock.h; sourceTree = ""; }; @@ -315,6 +317,7 @@ C9DC08111B90DE1B007A4DD0 /* PasscodeSignPlaceholderView.swift */, C9DC08131B90DE50007A4DD0 /* PasscodeSignButton.swift */, C9D3DF0A1B919CE4008561EB /* PasscodeLockView.xib */, + 6E2B4C0D1EE72C68005D20D0 /* DarkPasscodeLockView.xib */, ); path = Views; sourceTree = ""; @@ -511,6 +514,7 @@ files = ( C9DC07FC1B90D0A3007A4DD0 /* PasscodeLock.strings in Resources */, C9D3DF0B1B919CE4008561EB /* PasscodeLockView.xib in Resources */, + 6E2B4C0E1EE72C68005D20D0 /* DarkPasscodeLockView.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index 1eed5771..e54323e9 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -68,10 +68,17 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat passcodeLock.delegate = self notificationCenter = NotificationCenter.default } - - public convenience init(state: LockState, configuration: PasscodeLockConfigurationType, animateOnDismiss: Bool = true) { - - self.init(state: state.getState(), configuration: configuration, animateOnDismiss: animateOnDismiss) + + public convenience init(state: LockState, configuration: PasscodeLockConfigurationType, darkUI: Bool = false, animateOnDismiss: Bool = true) { + + if ( darkUI ) { + + self.init(state: state.getState(), configuration: configuration, animateOnDismiss: animateOnDismiss, nibName: "DarkPasscodeLockView", bundle: nil) + + } else { + + self.init(state: state.getState(), configuration: configuration, animateOnDismiss: animateOnDismiss) + } self.extraCallbacks = ( state == .enterPasscode || state == .enterOptionalPasscode ) diff --git a/PasscodeLock/Views/DarkPasscodeLockView.xib b/PasscodeLock/Views/DarkPasscodeLockView.xib new file mode 100644 index 00000000..3c695973 --- /dev/null +++ b/PasscodeLock/Views/DarkPasscodeLockView.xib @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fdf519b17ccf8f32f632431c572be3f146650e15 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Tue, 6 Jun 2017 22:29:20 +0300 Subject: [PATCH 17/32] utilitize darkUI in example --- PasscodeLockDemo/Base.lproj/Main.storyboard | 9 +++++++++ PasscodeLockDemo/PasscodeSettingsViewController.swift | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/PasscodeLockDemo/Base.lproj/Main.storyboard b/PasscodeLockDemo/Base.lproj/Main.storyboard index c51806b8..0a16279a 100644 --- a/PasscodeLockDemo/Base.lproj/Main.storyboard +++ b/PasscodeLockDemo/Base.lproj/Main.storyboard @@ -70,6 +70,13 @@ + @@ -80,10 +87,12 @@ + + diff --git a/PasscodeLockDemo/PasscodeSettingsViewController.swift b/PasscodeLockDemo/PasscodeSettingsViewController.swift index b9d7c5d5..1b75be4f 100644 --- a/PasscodeLockDemo/PasscodeSettingsViewController.swift +++ b/PasscodeLockDemo/PasscodeSettingsViewController.swift @@ -91,7 +91,7 @@ class PasscodeSettingsViewController: UIViewController { let repo = UserDefaultsPasscodeRepository() let config = PasscodeLockConfiguration(repository: repo) - let passcodeLock = PasscodeLockViewController(state: .enterOptionalPasscode, configuration: config) + let passcodeLock = PasscodeLockViewController(state: .enterOptionalPasscode, configuration: config, darkUI: sender.tag == 0 ? false : true) passcodeLock.successCallback = { lock in NSLog("Success") From 6cce11ef670144856ad12f2870ba6118248ecd37 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 00:15:00 +0300 Subject: [PATCH 18/32] Update README.md Correct GitHub repository for Podfile example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 33e5254b..3649d3e8 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ To integrate PasscodeLock into your Xcode project using CocoaPods, specify it in source 'https://github.com/CocoaPods/Specs.git' platform :ios, ‘8.0’ -pod 'PasscodeLock', :git => ‘https://github.com/oskarirauta/PasscodeLock.git' +pod 'PasscodeLock', :git => ‘https://github.com/oskarirauta/SwiftPasscodeLock.git' ``` Then, run the following command: From 69d1d1daf35f2934f799e5025676407e8e25b833 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 00:16:41 +0300 Subject: [PATCH 19/32] Update PasscodeLock.podspec Fix typos --- PasscodeLock.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PasscodeLock.podspec b/PasscodeLock.podspec index 78ce554a..00e682f1 100755 --- a/PasscodeLock.podspec +++ b/PasscodeLock.podspec @@ -4,7 +4,7 @@ s.version = '1.0.3' s.license = { :type => "MIT", :file => 'LICENSE.txt' } s.summary = 'An iOS passcode lock with Touch ID authentication written in Swift.' s.homepage = 'https://github.com/oskarirauta/SwiftPasscodeLock' -s.authors = { ‘Oskari Rauta’ => ‘’, ’Yanko Dimitrov' => '', 'Chris Ziogas' => '', } +s.authors = { 'Oskari Rauta' => '', 'Yanko Dimitrov' => '', 'Chris Ziogas' => '', } s.source = { :git => 'https://github.com/oskarirauta/SwiftPasscodeLock.git' } s.ios.deployment_target = '8.0' From c93f011eb6894e5d4be4622c21a02be13247aee6 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 00:19:06 +0300 Subject: [PATCH 20/32] Update README.md Update Podfile example --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 3649d3e8..ef02c353 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,9 @@ To integrate PasscodeLock into your Xcode project using CocoaPods, specify it in source 'https://github.com/CocoaPods/Specs.git' platform :ios, ‘8.0’ +use_frameworks! + +target 'your_target_name_here' pod 'PasscodeLock', :git => ‘https://github.com/oskarirauta/SwiftPasscodeLock.git' ``` From d148c77b64cec9c4cf345ae6863e32b06637da6b Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 00:26:24 +0300 Subject: [PATCH 21/32] Update PasscodeLock.podspec Include dark version of view --- PasscodeLock.podspec | 1 + 1 file changed, 1 insertion(+) diff --git a/PasscodeLock.podspec b/PasscodeLock.podspec index 00e682f1..16d9380b 100755 --- a/PasscodeLock.podspec +++ b/PasscodeLock.podspec @@ -14,6 +14,7 @@ s.source_files = 'PasscodeLock/*.{h,swift}', s.resources = [ 'PasscodeLock/Views/PasscodeLockView.xib', + 'PasscodeLock/Views/DarkPasscodeLockView.xib', 'PasscodeLock/en.lproj/*' ] From 5a0b31a4692a8844d8b8cdfa500d9cabd2968de3 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 01:36:59 +0300 Subject: [PATCH 22/32] Update PasscodeLockViewController.swift --- PasscodeLock/PasscodeLockViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index e54323e9..5211d964 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -106,6 +106,7 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + EnterPasscodeState.incorrectPasscodeAttempts = 0 updatePasscodeView() } From 2980cc16e025141569120adb2c4664b81f6eb3c5 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 01:49:13 +0300 Subject: [PATCH 23/32] Update PasscodeLockViewController.swift - Reset passcode attempts every time view comes up. - Let animation display to the end, before dismissing on too many passcode attempts. --- PasscodeLock/PasscodeLockViewController.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index 5211d964..06932eb7 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -281,9 +281,12 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat if (( maxAttempts >= 0) && ( attemptNo >= maxAttempts )) { if ( shouldDissmissOnTooManyAttempts ) { - dismissPasscodeLock(lock, completionHandler: { [weak self] _ in - self?.tooManyAttemptsCallback?(attemptNo) - }) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.6, execute: { + + dismissPasscodeLock(lock, completionHandler: { [weak self] _ in + self?.tooManyAttemptsCallback?(attemptNo) + }) + }) } else { self.tooManyAttemptsCallback?(attemptNo) } From 621698aa93feedfb9254693ece81e73ffe6779e4 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 01:51:09 +0300 Subject: [PATCH 24/32] Update PasscodeSettingsViewController.swift Fix a bad idea by reverting to older.... --- PasscodeLockDemo/PasscodeSettingsViewController.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/PasscodeLockDemo/PasscodeSettingsViewController.swift b/PasscodeLockDemo/PasscodeSettingsViewController.swift index 1b75be4f..741594eb 100644 --- a/PasscodeLockDemo/PasscodeSettingsViewController.swift +++ b/PasscodeLockDemo/PasscodeSettingsViewController.swift @@ -71,7 +71,6 @@ class PasscodeSettingsViewController: UIViewController { } } - passcodeVC.modalPresentationStyle = .overCurrentContext present(passcodeVC, animated: true, completion: nil) } @@ -82,7 +81,6 @@ class PasscodeSettingsViewController: UIViewController { let passcodeLock = PasscodeLockViewController(state: .changePasscode, configuration: config) - passcodeLock.modalPresentationStyle = .overCurrentContext present(passcodeLock, animated: true, completion: nil) } @@ -109,7 +107,6 @@ class PasscodeSettingsViewController: UIViewController { NSLog("Maximum amount of %d attempts reached", attemptNo) } - passcodeLock.modalPresentationStyle = .overCurrentContext present(passcodeLock, animated: true, completion: nil) } From 35d0652cbb51dd22518577e80f8179b1c8a8b4f9 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 7 Jun 2017 13:12:46 +0300 Subject: [PATCH 25/32] Update PasscodeLockViewController.swift minor fix --- PasscodeLock/PasscodeLockViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index 06932eb7..2936bdac 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -283,7 +283,7 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat if ( shouldDissmissOnTooManyAttempts ) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.6, execute: { - dismissPasscodeLock(lock, completionHandler: { [weak self] _ in + self.dismissPasscodeLock(lock, completionHandler: { [weak self] _ in self?.tooManyAttemptsCallback?(attemptNo) }) }) From 763a2a3672fed7850391d2ec76c4cf1643b9b475 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 5 Jul 2017 20:09:48 +0300 Subject: [PATCH 26/32] Update PasscodeLock.strings --- PasscodeLock/en.lproj/PasscodeLock.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PasscodeLock/en.lproj/PasscodeLock.strings b/PasscodeLock/en.lproj/PasscodeLock.strings index f71ef86c..7d2393de 100755 --- a/PasscodeLock/en.lproj/PasscodeLock.strings +++ b/PasscodeLock/en.lproj/PasscodeLock.strings @@ -19,7 +19,7 @@ "PasscodeLockConfirmDescription" = "Enter the passcode again."; /* Change Passcode State */ -"PasscodeLockChangeTitle" = "Enter Old Passcode"; +"PasscodeLockChangeTitle" = "Change Passcode"; "PasscodeLockChangeDescription" = "Enter your old passcode."; /* Passcode Mismatch State */ @@ -30,4 +30,4 @@ "PasscodeLockTouchIDReason" = "Authentication required to proceed"; /* Touch ID Fallback Button */ -"PasscodeLockTouchIDButton" = "Enter Passcode"; \ No newline at end of file +"PasscodeLockTouchIDButton" = "Enter Passcode"; From 77921a427e88030cd594fd90820b7831aa8cbd9c Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Wed, 5 Jul 2017 20:16:02 +0300 Subject: [PATCH 27/32] Update PasscodeLockViewController.swift --- PasscodeLock/PasscodeLockViewController.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index 2936bdac..356883f7 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -45,6 +45,9 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat open var animateOnDismiss: Bool open var notificationCenter: NotificationCenter? + open var overrideTitleText: String? = nil + open var overrideDescriptionText: String? = nil + internal let passcodeConfiguration: PasscodeLockConfigurationType internal var passcodeLock: PasscodeLockType internal var isPlaceholdersAnimationCompleted = true @@ -118,11 +121,16 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat authenticateWithBiometrics() } } + + open override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + updatePasscodeView() + } internal func updatePasscodeView() { - titleLabel?.text = passcodeLock.state.title - descriptionLabel?.text = passcodeLock.state.description + titleLabel?.text = ( overrideTitleText != nil ? overrideTitleText! : passcodeLock.state.title ) + descriptionLabel?.text = ( overrideDescriptionText != nil ? overrideDescriptionText! : passcodeLock.state.description ) cancelButton?.isHidden = !passcodeLock.state.isCancellableAction touchIDButton?.isHidden = !passcodeLock.isTouchIDAllowed || passcodeLock.configuration.shouldDisableTouchIDButton } From 9a78a0cdbae4b34fc993366575e1c370bd1f76fc Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Thu, 6 Jul 2017 23:57:26 +0300 Subject: [PATCH 28/32] Update PasscodeLockViewController.swift --- PasscodeLock/PasscodeLockViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index 356883f7..b4f2a881 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -151,6 +151,8 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat open func appWillEnterForegroundHandler(_ notification: Notification) { + shouldTryToAuthenticateWithBiometrics = true + if passcodeConfiguration.shouldRequestTouchIDImmediately { authenticateWithBiometrics() } From f520bc4df92d039fc5dcc39fa7d8133c13b63bfe Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Thu, 13 Jul 2017 01:10:12 +0300 Subject: [PATCH 29/32] Update PasscodeLockViewController.swift changed execution order of callbacks.. --- PasscodeLock/PasscodeLockViewController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index b4f2a881..1e738280 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -205,10 +205,10 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat if presentingViewController?.presentedViewController == self { dismiss(animated: animateOnDismiss, completion: { [weak self] _ in - - self?.dismissCompletionCallback?() - + completionHandler?() + + self?.dismissCompletionCallback?() }) return @@ -219,9 +219,9 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat navigationController?.popViewController(animated: animateOnDismiss) } - dismissCompletionCallback?() - completionHandler?() + + dismissCompletionCallback?() } // MARK: - Animations From ed3e0a59126e8bf8adcd07992efced36fae7df33 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Thu, 28 Mar 2019 08:23:04 +0200 Subject: [PATCH 30/32] Release 1.1.0 Swift 5 syntax --- PasscodeLock.podspec | 5 +- PasscodeLock.xcodeproj/project.pbxproj | 113 +++++++++++++----- .../xcschemes/PasscodeLock.xcscheme | 4 +- PasscodeLock/Info.plist | 2 +- PasscodeLock/PasscodeLock/PasscodeLock.swift | 2 +- PasscodeLock/PasscodeLockPresenter.swift | 14 +-- PasscodeLock/PasscodeLockViewController.swift | 26 ++-- PasscodeLock/Protocols/PasscodeLockType.swift | 2 +- PasscodeLock/Views/PasscodeSignButton.swift | 4 +- .../Fakes/FakePasscodeLock.swift | 4 +- .../Fakes/FakePasscodeLockConfiguration.swift | 4 +- .../Fakes/FakePasscodeLockDelegate.swift | 10 +- .../Fakes/FakePasscodeRepository.swift | 2 +- .../Fakes/FakePasscodeState.swift | 2 +- .../ChangePasscodeStateTests.swift | 4 +- .../ConfirmPasscodeStateTests.swift | 6 +- .../EnterPasscodeStateTests.swift | 18 +-- .../PasscodeLock/PasscodeLockTests.swift | 6 +- .../PasscodeLock/SetPasscodeStateTests.swift | 2 +- 19 files changed, 146 insertions(+), 84 deletions(-) diff --git a/PasscodeLock.podspec b/PasscodeLock.podspec index 16d9380b..b755ef4f 100755 --- a/PasscodeLock.podspec +++ b/PasscodeLock.podspec @@ -1,13 +1,14 @@ Pod::Spec.new do |s| s.name = 'PasscodeLock' -s.version = '1.0.3' +s.version = '1.1.0' s.license = { :type => "MIT", :file => 'LICENSE.txt' } s.summary = 'An iOS passcode lock with Touch ID authentication written in Swift.' s.homepage = 'https://github.com/oskarirauta/SwiftPasscodeLock' s.authors = { 'Oskari Rauta' => '', 'Yanko Dimitrov' => '', 'Chris Ziogas' => '', } s.source = { :git => 'https://github.com/oskarirauta/SwiftPasscodeLock.git' } -s.ios.deployment_target = '8.0' +s.ios.deployment_target = '9.0' +s.swift_version = '5.0' s.source_files = 'PasscodeLock/*.{h,swift}', 'PasscodeLock/*/*.{swift}' diff --git a/PasscodeLock.xcodeproj/project.pbxproj b/PasscodeLock.xcodeproj/project.pbxproj index f1d6bbf8..9c2b8bca 100644 --- a/PasscodeLock.xcodeproj/project.pbxproj +++ b/PasscodeLock.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -458,16 +458,16 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0810; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Yanko Dimitrov"; TargetAttributes = { C99EAF3E1B90B05700D61E1B = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0810; + LastSwiftMigration = 1020; }; C99EAF481B90B05700D61E1B = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0830; + LastSwiftMigration = 1020; }; C9D3DF0F1B91AD11008561EB = { CreatedOnToolsVersion = 7.0; @@ -486,8 +486,8 @@ }; }; buildConfigurationList = C99EAF391B90B05700D61E1B /* Build configuration list for PBXProject "PasscodeLock" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -690,14 +690,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -721,7 +729,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -740,14 +748,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -765,10 +781,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -787,12 +804,16 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = PasscodeLock/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLock; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -807,11 +828,15 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = PasscodeLock/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLock; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -820,12 +845,16 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = PasscodeLockTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PasscodeLockTests/PasscodeLockTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -834,11 +863,15 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = PasscodeLockTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PasscodeLockTests/PasscodeLockTests-Bridging-Header.h"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -849,10 +882,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = PasscodeLockDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockDemo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -864,10 +900,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = PasscodeLockDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockDemo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -878,10 +917,14 @@ BUNDLE_LOADER = "$(TEST_HOST)"; INFOPLIST_FILE = PasscodeLockDemoTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockDemoTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PasscodeLockDemo.app/PasscodeLockDemo"; }; name = Debug; @@ -892,10 +935,14 @@ BUNDLE_LOADER = "$(TEST_HOST)"; INFOPLIST_FILE = PasscodeLockDemoTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockDemoTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PasscodeLockDemo.app/PasscodeLockDemo"; }; name = Release; @@ -905,10 +952,14 @@ buildSettings = { INFOPLIST_FILE = PasscodeLockDemoUITests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockDemoUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TEST_TARGET_NAME = PasscodeLockDemo; USES_XCTRUNNER = YES; }; @@ -919,10 +970,14 @@ buildSettings = { INFOPLIST_FILE = PasscodeLockDemoUITests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.yankodimitrov.PasscodeLockDemoUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TEST_TARGET_NAME = PasscodeLockDemo; USES_XCTRUNNER = YES; }; diff --git a/PasscodeLock.xcodeproj/xcshareddata/xcschemes/PasscodeLock.xcscheme b/PasscodeLock.xcodeproj/xcshareddata/xcschemes/PasscodeLock.xcscheme index 79e7b235..230902f8 100644 --- a/PasscodeLock.xcodeproj/xcshareddata/xcschemes/PasscodeLock.xcscheme +++ b/PasscodeLock.xcodeproj/xcshareddata/xcschemes/PasscodeLock.xcscheme @@ -1,6 +1,6 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.1.0 CFBundleSignature ???? CFBundleVersion diff --git a/PasscodeLock/PasscodeLock/PasscodeLock.swift b/PasscodeLock/PasscodeLock/PasscodeLock.swift index 82b5fc3c..f5b306d7 100644 --- a/PasscodeLock/PasscodeLock/PasscodeLock.swift +++ b/PasscodeLock/PasscodeLock/PasscodeLock.swift @@ -12,7 +12,7 @@ import LocalAuthentication open class PasscodeLock: PasscodeLockType { open weak var delegate: PasscodeLockTypeDelegate? - open let configuration: PasscodeLockConfigurationType + open var configuration: PasscodeLockConfigurationType open var repository: PasscodeRepositoryType { return configuration.repository diff --git a/PasscodeLock/PasscodeLockPresenter.swift b/PasscodeLock/PasscodeLockPresenter.swift index 3904e3ef..c6a9c071 100644 --- a/PasscodeLock/PasscodeLockPresenter.swift +++ b/PasscodeLock/PasscodeLockPresenter.swift @@ -16,7 +16,7 @@ open class PasscodeLockPresenter { let window = UIWindow(frame: UIScreen.main.bounds) - window.windowLevel = 0 + window.windowLevel = UIWindow.Level(rawValue: 0) window.makeKeyAndVisible() return window @@ -25,12 +25,12 @@ open class PasscodeLockPresenter { fileprivate let passcodeConfiguration: PasscodeLockConfigurationType open var isPasscodePresented = false - open let passcodeLockVC: PasscodeLockViewController + open var passcodeLockVC: PasscodeLockViewController public init(mainWindow window: UIWindow?, configuration: PasscodeLockConfigurationType, viewController: PasscodeLockViewController) { mainWindow = window - mainWindow?.windowLevel = 1 + mainWindow?.windowLevel = UIWindow.Level(rawValue: 1) passcodeConfiguration = configuration passcodeLockVC = viewController @@ -64,7 +64,7 @@ open class PasscodeLockPresenter { guard !isPasscodePresented else { return } isPasscodePresented = true - passcodeLockWindow.windowLevel = 2 + passcodeLockWindow.windowLevel = UIWindow.Level(rawValue: 2) toggleKeyboardVisibility(hide: true) @@ -83,7 +83,7 @@ open class PasscodeLockPresenter { open func dismissPasscodeLock(animated: Bool = true) { isPasscodePresented = false - mainWindow?.windowLevel = 1 + mainWindow?.windowLevel = UIWindow.Level(rawValue: 1) mainWindow?.makeKeyAndVisible() if animated { @@ -99,14 +99,14 @@ open class PasscodeLockPresenter { }, completion: { [weak self] _ in - self?.passcodeLockWindow.windowLevel = 0 + self?.passcodeLockWindow.windowLevel = UIWindow.Level(rawValue: 0) self?.passcodeLockWindow.rootViewController = nil self?.passcodeLockWindow.alpha = 1 self?.toggleKeyboardVisibility(hide: false) } ) } else { - passcodeLockWindow.windowLevel = 0 + passcodeLockWindow.windowLevel = UIWindow.Level(rawValue: 0) passcodeLockWindow.rootViewController = nil toggleKeyboardVisibility(hide: false) } diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index 1e738280..49d07a8e 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -139,17 +139,17 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat fileprivate func setupEvents() { - notificationCenter?.addObserver(self, selector: #selector(PasscodeLockViewController.appWillEnterForegroundHandler(_:)), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil) - notificationCenter?.addObserver(self, selector: #selector(PasscodeLockViewController.appDidEnterBackgroundHandler(_:)), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil) + notificationCenter?.addObserver(self, selector: #selector(PasscodeLockViewController.appWillEnterForegroundHandler(_:)), name: UIApplication.willEnterForegroundNotification, object: nil) + notificationCenter?.addObserver(self, selector: #selector(PasscodeLockViewController.appDidEnterBackgroundHandler(_:)), name: UIApplication.didEnterBackgroundNotification, object: nil) } fileprivate func clearEvents() { - notificationCenter?.removeObserver(self, name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil) - notificationCenter?.removeObserver(self, name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil) + notificationCenter?.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) + notificationCenter?.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil) } - open func appWillEnterForegroundHandler(_ notification: Notification) { + @objc open func appWillEnterForegroundHandler(_ notification: Notification) { shouldTryToAuthenticateWithBiometrics = true @@ -158,7 +158,7 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat } } - open func appDidEnterBackgroundHandler(_ notification: Notification) { + @objc open func appDidEnterBackgroundHandler(_ notification: Notification) { shouldTryToAuthenticateWithBiometrics = false } @@ -174,7 +174,8 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat @IBAction func cancelButtonTap(_ sender: UIButton) { - dismissPasscodeLock(passcodeLock, completionHandler: { [weak self] _ in + self.dismissPasscodeLock(passcodeLock, completionHandler: { + [weak self] in self?.cancelCompletionCallback?() }) } @@ -204,10 +205,9 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat // if presented as modal if presentingViewController?.presentedViewController == self { - dismiss(animated: animateOnDismiss, completion: { [weak self] _ in - + dismiss(animated: animateOnDismiss, completion: { + [weak self] in completionHandler?() - self?.dismissCompletionCallback?() }) @@ -275,7 +275,8 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat deleteSignButton?.isEnabled = true animatePlaceholders(placeholders, toState: .inactive) - dismissPasscodeLock(lock, completionHandler: { [weak self] _ in + dismissPasscodeLock(lock, completionHandler: { + [weak self] in self?.successCallback?(lock) }) } @@ -293,7 +294,8 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat if ( shouldDissmissOnTooManyAttempts ) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.6, execute: { - self.dismissPasscodeLock(lock, completionHandler: { [weak self] _ in + self.dismissPasscodeLock(lock, completionHandler: { + [weak self] in self?.tooManyAttemptsCallback?(attemptNo) }) }) diff --git a/PasscodeLock/Protocols/PasscodeLockType.swift b/PasscodeLock/Protocols/PasscodeLockType.swift index 434c87d6..c5390112 100644 --- a/PasscodeLock/Protocols/PasscodeLockType.swift +++ b/PasscodeLock/Protocols/PasscodeLockType.swift @@ -10,7 +10,7 @@ import Foundation public protocol PasscodeLockType { - weak var delegate: PasscodeLockTypeDelegate? {get set} + var delegate: PasscodeLockTypeDelegate? {get set} var configuration: PasscodeLockConfigurationType {get} var repository: PasscodeRepositoryType {get} var state: PasscodeLockStateType {get} diff --git a/PasscodeLock/Views/PasscodeSignButton.swift b/PasscodeLock/Views/PasscodeSignButton.swift index 01f7eff6..0ed0d7fe 100644 --- a/PasscodeLock/Views/PasscodeSignButton.swift +++ b/PasscodeLock/Views/PasscodeSignButton.swift @@ -75,12 +75,12 @@ open class PasscodeSignButton: UIButton { addTarget(self, action: #selector(PasscodeSignButton.handleTouchUp), for: [.touchUpInside, .touchDragOutside, .touchCancel]) } - func handleTouchDown() { + @objc func handleTouchDown() { animateBackgroundColor(highlightBackgroundColor) } - func handleTouchUp() { + @objc func handleTouchUp() { animateBackgroundColor(defaultBackgroundColor) } diff --git a/PasscodeLockTests/Fakes/FakePasscodeLock.swift b/PasscodeLockTests/Fakes/FakePasscodeLock.swift index 518710e3..8975eaa9 100644 --- a/PasscodeLockTests/Fakes/FakePasscodeLock.swift +++ b/PasscodeLockTests/Fakes/FakePasscodeLock.swift @@ -25,7 +25,7 @@ class FakePasscodeLock: PasscodeLockType { self.configuration = configuration } - func addSign(sign: String) { + func addSign(_ sign: String) { } @@ -33,7 +33,7 @@ class FakePasscodeLock: PasscodeLockType { } - func changeStateTo(state: PasscodeLockStateType) { + func changeStateTo(_ state: PasscodeLockStateType) { lockState = state changeStateCalled = true diff --git a/PasscodeLockTests/Fakes/FakePasscodeLockConfiguration.swift b/PasscodeLockTests/Fakes/FakePasscodeLockConfiguration.swift index 46c871bc..fd3004b8 100644 --- a/PasscodeLockTests/Fakes/FakePasscodeLockConfiguration.swift +++ b/PasscodeLockTests/Fakes/FakePasscodeLockConfiguration.swift @@ -16,7 +16,9 @@ class FakePasscodeLockConfiguration: PasscodeLockConfigurationType { let maximumInccorectPasscodeAttempts = 3 let shouldRequestTouchIDImmediately = false var touchIdReason: String? = nil - + var shouldDisableTouchIDButton: Bool = true + var shouldDismissOnTooManyAttempts: Bool = true + init(repository: PasscodeRepositoryType) { self.repository = repository diff --git a/PasscodeLockTests/Fakes/FakePasscodeLockDelegate.swift b/PasscodeLockTests/Fakes/FakePasscodeLockDelegate.swift index 3d82b9bf..72d4b85a 100644 --- a/PasscodeLockTests/Fakes/FakePasscodeLockDelegate.swift +++ b/PasscodeLockTests/Fakes/FakePasscodeLockDelegate.swift @@ -10,9 +10,9 @@ import Foundation class FakePasscodeLockDelegate: PasscodeLockTypeDelegate { - func passcodeLockDidSucceed(lock: PasscodeLockType) {} - func passcodeLockDidFail(lock: PasscodeLockType) {} - func passcodeLockDidChangeState(lock: PasscodeLockType) {} - func passcodeLock(lock: PasscodeLockType, addedSignAtIndex index: Int) {} - func passcodeLock(lock: PasscodeLockType, removedSignAtIndex index: Int) {} + func passcodeLockDidSucceed(_ lock: PasscodeLockType) {} + func passcodeLockDidFail(_ lock: PasscodeLockType) {} + func passcodeLockDidChangeState(_ lock: PasscodeLockType) {} + func passcodeLock(_ lock: PasscodeLockType, addedSignAtIndex index: Int) {} + func passcodeLock(_ lock: PasscodeLockType, removedSignAtIndex index: Int) {} } diff --git a/PasscodeLockTests/Fakes/FakePasscodeRepository.swift b/PasscodeLockTests/Fakes/FakePasscodeRepository.swift index 657b67fc..9c210521 100644 --- a/PasscodeLockTests/Fakes/FakePasscodeRepository.swift +++ b/PasscodeLockTests/Fakes/FakePasscodeRepository.swift @@ -18,7 +18,7 @@ class FakePasscodeRepository: PasscodeRepositoryType { var savePasscodeCalled = false var savedPasscode = [String]() - func savePasscode(passcode: [String]) { + func savePasscode(_ passcode: [String]) { savePasscodeCalled = true savedPasscode = passcode diff --git a/PasscodeLockTests/Fakes/FakePasscodeState.swift b/PasscodeLockTests/Fakes/FakePasscodeState.swift index 61bc3e3c..e2b345a4 100644 --- a/PasscodeLockTests/Fakes/FakePasscodeState.swift +++ b/PasscodeLockTests/Fakes/FakePasscodeState.swift @@ -21,7 +21,7 @@ class FakePasscodeState: PasscodeLockStateType { init() {} - func acceptPasscode(passcode: [String], fromLock lock: PasscodeLockType) { + func acceptPasscode(_ passcode: [String], fromLock lock: PasscodeLockType) { acceptedPasscode = passcode acceptPaccodeCalled = true diff --git a/PasscodeLockTests/PasscodeLock/ChangePasscodeStateTests.swift b/PasscodeLockTests/PasscodeLock/ChangePasscodeStateTests.swift index eade20ca..721b5ce5 100644 --- a/PasscodeLockTests/PasscodeLock/ChangePasscodeStateTests.swift +++ b/PasscodeLockTests/PasscodeLock/ChangePasscodeStateTests.swift @@ -31,7 +31,7 @@ class ChangePasscodeStateTests: XCTestCase { var didChangedState = false - override func passcodeLockDidChangeState(lock: PasscodeLockType) { + override func passcodeLockDidChangeState(_ lock: PasscodeLockType) { didChangedState = true } @@ -52,7 +52,7 @@ class ChangePasscodeStateTests: XCTestCase { var called = false - override func passcodeLockDidFail(lock: PasscodeLockType) { + override func passcodeLockDidFail(_ lock: PasscodeLockType) { called = true } diff --git a/PasscodeLockTests/PasscodeLock/ConfirmPasscodeStateTests.swift b/PasscodeLockTests/PasscodeLock/ConfirmPasscodeStateTests.swift index f122f702..47b9dfbc 100644 --- a/PasscodeLockTests/PasscodeLock/ConfirmPasscodeStateTests.swift +++ b/PasscodeLockTests/PasscodeLock/ConfirmPasscodeStateTests.swift @@ -32,7 +32,7 @@ class ConfirmPasscodeStateTests: XCTestCase { var called = false - override func passcodeLockDidSucceed(lock: PasscodeLockType) { + override func passcodeLockDidSucceed(_ lock: PasscodeLockType) { called = true } @@ -61,12 +61,12 @@ class ConfirmPasscodeStateTests: XCTestCase { var didFailed = false var didChangedState = false - override func passcodeLockDidFail(lock: PasscodeLockType) { + override func passcodeLockDidFail(_ lock: PasscodeLockType) { didFailed = true } - override func passcodeLockDidChangeState(lock: PasscodeLockType) { + override func passcodeLockDidChangeState(_ lock: PasscodeLockType) { didChangedState = true } diff --git a/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift b/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift index 87095ff5..f17b43eb 100644 --- a/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift +++ b/PasscodeLockTests/PasscodeLock/EnterPasscodeStateTests.swift @@ -8,7 +8,7 @@ import XCTest -class NotificaionObserver: NSObject { +class NotificationObserver: NSObject { var called = false var callCounter = 0 @@ -17,10 +17,10 @@ class NotificaionObserver: NSObject { let center = NotificationCenter.default - center.addObserver(self, selector: "handle:", name: NSNotification.Name(rawValue: notification), object: nil) + center.addObserver(self, selector: #selector(self.handle), name: NSNotification.Name(rawValue: notification), object: nil) } - func handle(notification: NSNotification) { + @objc func handle(notification: NSNotification) { called = true callCounter += 1 @@ -50,7 +50,7 @@ class EnterPasscodeStateTests: XCTestCase { var called = false - override func passcodeLockDidSucceed(lock: PasscodeLockType) { + override func passcodeLockDidSucceed(_ lock: PasscodeLockType) { called = true } @@ -70,7 +70,7 @@ class EnterPasscodeStateTests: XCTestCase { var called = false - override func passcodeLockDidFail(lock: PasscodeLockType) { + override func passcodeLockDidFail(_ lock: PasscodeLockType) { called = true } @@ -86,9 +86,9 @@ class EnterPasscodeStateTests: XCTestCase { func testIncorrectPasscodeNotification() { - let observer = NotificaionObserver() + let observer = NotificationObserver() - observer.observe(PasscodeLockIncorrectPasscodeNotification) + observer.observe(notification: PasscodeLockIncorrectPasscodeNotification) passcodeState.acceptPasscode(["0"], fromLock: passcodeLock) passcodeState.acceptPasscode(["0"], fromLock: passcodeLock) @@ -99,9 +99,9 @@ class EnterPasscodeStateTests: XCTestCase { func testIncorrectPasscodeSendNotificationOnce() { - let observer = NotificaionObserver() + let observer = NotificationObserver() - observer.observe(PasscodeLockIncorrectPasscodeNotification) + observer.observe(notification: PasscodeLockIncorrectPasscodeNotification) passcodeState.acceptPasscode(["0"], fromLock: passcodeLock) passcodeState.acceptPasscode(["0"], fromLock: passcodeLock) diff --git a/PasscodeLockTests/PasscodeLock/PasscodeLockTests.swift b/PasscodeLockTests/PasscodeLock/PasscodeLockTests.swift index efb192a3..0ec9f6b9 100644 --- a/PasscodeLockTests/PasscodeLock/PasscodeLockTests.swift +++ b/PasscodeLockTests/PasscodeLock/PasscodeLockTests.swift @@ -29,7 +29,7 @@ class PasscodeLockTests: XCTestCase { var called = false - override func passcodeLockDidChangeState(lock: PasscodeLockType) { + override func passcodeLockDidChangeState(_ lock: PasscodeLockType) { called = true } @@ -51,7 +51,7 @@ class PasscodeLockTests: XCTestCase { var called = false var signIndex = 0 - override func passcodeLock(lock: PasscodeLockType, addedSignAtIndex index: Int) { + override func passcodeLock(_ lock: PasscodeLockType, addedSignAtIndex index: Int) { called = true signIndex = index @@ -78,7 +78,7 @@ class PasscodeLockTests: XCTestCase { var called = false var signIndex = 0 - override func passcodeLock(lock: PasscodeLockType, removedSignAtIndex index: Int) { + override func passcodeLock(_ lock: PasscodeLockType, removedSignAtIndex index: Int) { called = true signIndex = index diff --git a/PasscodeLockTests/PasscodeLock/SetPasscodeStateTests.swift b/PasscodeLockTests/PasscodeLock/SetPasscodeStateTests.swift index 20ef1214..e90429a0 100644 --- a/PasscodeLockTests/PasscodeLock/SetPasscodeStateTests.swift +++ b/PasscodeLockTests/PasscodeLock/SetPasscodeStateTests.swift @@ -31,7 +31,7 @@ class SetPasscodeStateTests: XCTestCase { var didChangedState = false - override func passcodeLockDidChangeState(lock: PasscodeLockType) { + override func passcodeLockDidChangeState(_ lock: PasscodeLockType) { didChangedState = true } From 4c4d04e5e5fbfa1dfe2ca3996311d92ca015a7d5 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Thu, 28 Mar 2019 08:30:02 +0200 Subject: [PATCH 31/32] Release 1.1.1 --- PasscodeLock/Info.plist | 2 +- PasscodeLock/PasscodeLock/PasscodeLock.swift | 4 +++- .../Protocols/PasscodeLockConfigurationType.swift | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/PasscodeLock/Info.plist b/PasscodeLock/Info.plist index 09bc9720..c6f194eb 100644 --- a/PasscodeLock/Info.plist +++ b/PasscodeLock/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.1.0 + 1.1.1 CFBundleSignature ???? CFBundleVersion diff --git a/PasscodeLock/PasscodeLock/PasscodeLock.swift b/PasscodeLock/PasscodeLock/PasscodeLock.swift index f5b306d7..e2cbbc60 100644 --- a/PasscodeLock/PasscodeLock/PasscodeLock.swift +++ b/PasscodeLock/PasscodeLock/PasscodeLock.swift @@ -44,7 +44,9 @@ open class PasscodeLock: PasscodeLockType { if passcode.count >= configuration.passcodeLength { - lockState.acceptPasscode(passcode, fromLock: self) + // handles "requires exclusive access" error at Swift 4 + var lockStateCopy = lockState + lockStateCopy.acceptPasscode(passcode, fromLock: self) passcode.removeAll(keepingCapacity: true) } } diff --git a/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift b/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift index f0aa2593..921df911 100644 --- a/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift +++ b/PasscodeLock/Protocols/PasscodeLockConfigurationType.swift @@ -19,3 +19,15 @@ public protocol PasscodeLockConfigurationType { var maximumInccorectPasscodeAttempts: Int {get} var shouldDismissOnTooManyAttempts: Bool {get} } + +public extension PasscodeLockConfigurationType { + + var passcodeLength: Int { + return 4 + } + + var maximumInccorectPasscodeAttempts: Int { + return -1 + } + +} From 69a0850ae42ac284978ff7cf73dd34f0e76beab3 Mon Sep 17 00:00:00 2001 From: Oskari Rauta Date: Thu, 28 Mar 2019 08:50:23 +0200 Subject: [PATCH 32/32] Release 1.1.2 --- PasscodeLock.podspec | 2 +- PasscodeLock/Info.plist | 2 +- PasscodeLock/PasscodeLockViewController.swift | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/PasscodeLock.podspec b/PasscodeLock.podspec index b755ef4f..739556fc 100755 --- a/PasscodeLock.podspec +++ b/PasscodeLock.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PasscodeLock' -s.version = '1.1.0' +s.version = '1.1.2' s.license = { :type => "MIT", :file => 'LICENSE.txt' } s.summary = 'An iOS passcode lock with Touch ID authentication written in Swift.' s.homepage = 'https://github.com/oskarirauta/SwiftPasscodeLock' diff --git a/PasscodeLock/Info.plist b/PasscodeLock/Info.plist index c6f194eb..3034b22c 100644 --- a/PasscodeLock/Info.plist +++ b/PasscodeLock/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.1.1 + 1.1.2 CFBundleSignature ???? CFBundleVersion diff --git a/PasscodeLock/PasscodeLockViewController.swift b/PasscodeLock/PasscodeLockViewController.swift index 49d07a8e..1fac1e37 100644 --- a/PasscodeLock/PasscodeLockViewController.swift +++ b/PasscodeLock/PasscodeLockViewController.swift @@ -48,12 +48,12 @@ open class PasscodeLockViewController: UIViewController, PasscodeLockTypeDelegat open var overrideTitleText: String? = nil open var overrideDescriptionText: String? = nil - internal let passcodeConfiguration: PasscodeLockConfigurationType - internal var passcodeLock: PasscodeLockType - internal var isPlaceholdersAnimationCompleted = true - internal var extraCallbacks = false + open var passcodeConfiguration: PasscodeLockConfigurationType + open var passcodeLock: PasscodeLockType + open var isPlaceholdersAnimationCompleted = true + open var extraCallbacks = false - fileprivate var shouldTryToAuthenticateWithBiometrics = true + open var shouldTryToAuthenticateWithBiometrics = true // MARK: - Initializers