From 8a01633e03c25a24fbd317487ed03422cd6b6da9 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Thu, 22 Mar 2018 19:12:43 +0300 Subject: [PATCH 01/12] Update for swift 4 --- .../View/BasePassCodeViewController.swift | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 5ad2563..ca8aacc 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal @@ -47,7 +47,7 @@ public enum PassCodeControllerState { } /// Base view controller that operates with pass code -open class BasePassCodeViewController: UIViewController { +open class BasePassCodeViewController: UIViewController, ConfigurableController { public var viewModel: BasePassCodeViewModel! @@ -59,7 +59,7 @@ open class BasePassCodeViewController: UIViewController { public let disposeBag = DisposeBag() - fileprivate lazy var fakeTextField: UITextField = { + private lazy var fakeTextField: UITextField = { let fakeTextField = UITextField() fakeTextField.isSecureTextEntry = true fakeTextField.keyboardType = .numberPad @@ -113,7 +113,7 @@ open class BasePassCodeViewController: UIViewController { resetDotsUI() } - fileprivate func resetDotsUI() { + private func resetDotsUI() { fakeTextField.text = nil dotStackView.arrangedSubviews .flatMap { $0 as? UIImageView } @@ -129,7 +129,7 @@ open class BasePassCodeViewController: UIViewController { imageView.image = imageFor(type: state) } - fileprivate func setStates(for passCodeText: String) { + private func setStates(for passCodeText: String) { var statesArray: [PinImageType] = [] for characterIndex in 0.. Date: Thu, 22 Mar 2018 19:49:53 +0300 Subject: [PATCH 02/12] Update configuration --- .../Model/PassCodeConfiguration.swift | 20 ++++++++----------- .../View/BasePassCodeViewController.swift | 4 ++-- .../ViewModel/BasePassCodeViewModel.swift | 17 ++++++++-------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift index d48d8e5..a8b5931 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift @@ -24,26 +24,22 @@ public struct PassCodeConfiguration { /// Pass code length - public var passCodeCharactersNumber: UInt = 4 + public let passCodeLength: Int + /// Incorrect pass code attempts count - public var maxAttemptsLoginNumber: UInt = 5 + public let maxAttemptsNumber: Int /// Clear input progress when application goes to background - public var shouldResetWhenGoBackground: Bool = true + public let shouldResetWhenGoBackground: Bool - private init() {} - - init?(passCodeCharactersNumber: UInt) { - guard passCodeCharactersNumber > 0 else { - assertionFailure("passCodeCharactersNumber must be greater then 0") - return nil - } - self.passCodeCharactersNumber = passCodeCharactersNumber + public init(passCodeLength: Int = 4, maxAttemptsNumber: Int = 5, shouldResetWhenGoBackground: Bool = true) { + self.passCodeLength = passCodeLength + self.maxAttemptsNumber = maxAttemptsNumber + self.shouldResetWhenGoBackground = shouldResetWhenGoBackground } /// Returns configuration with default values public static var defaultConfiguration: PassCodeConfiguration { return PassCodeConfiguration() } - } diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index ca8aacc..21d7877 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -102,7 +102,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController private func initialDotNumberConfiguration() { dotStackView.arrangedSubviews.forEach { dotStackView.removeArrangedSubview($0) } - for _ in 0..(nil) + private let validationResultHolder = Variable(nil) var validationResult: Driver { return validationResultHolder.asDriver() } - fileprivate let passCodeControllerStateHolder = Variable(.enter) + private let passCodeControllerStateHolder = Variable(.enter) public var passCodeControllerState: Driver { return passCodeControllerStateHolder.asDriver() } private let passCodeText = Variable(nil) - fileprivate var attemptsNumber = 0 + private var attemptsNumber = 0 - fileprivate lazy var passCodeHolder: PassCodeHolderProtocol = { - return PassCodeHolderBuilder.build(with: self.controllerType) - }() + private lazy var passCodeHolder: PassCodeHolderProtocol = PassCodeHolderBuilder.build(with: self.controllerType) public init(controllerType: PassCodeControllerType, passCodeConfiguration: PassCodeConfiguration, @@ -76,7 +75,7 @@ open class BasePassCodeViewModel: BaseViewModel { .distinctUntilChanged { $0 == $1 } .drive(onNext: { [weak self] passCode in if let passCode = passCode, - passCode.characters.count == Int(self?.passCodeConfiguration.passCodeCharactersNumber ?? 0) { + passCode.characters.count == Int(self?.passCodeConfiguration.passCodeLength ?? 0) { self?.set(passCode: passCode) } }) @@ -184,8 +183,8 @@ extension BasePassCodeViewModel { validationResult = .inValid(.wrongCode) } - if (!validationResult.isValid && attemptsNumber == Int(passCodeConfiguration.maxAttemptsLoginNumber)) || - attemptsNumber > Int(passCodeConfiguration.maxAttemptsLoginNumber) { + if (!validationResult.isValid && attemptsNumber == Int(passCodeConfiguration.maxAttemptsNumber)) || + attemptsNumber > Int(passCodeConfiguration.maxAttemptsNumber) { validationResult = .inValid(.tooManyAttempts) } } From ce2c69e854fc0c7cdd664f00b331582d0781f50e Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 23 Mar 2018 12:48:36 +0300 Subject: [PATCH 03/12] Passcode refactoring & improvements --- .../View/BasePassCodeViewController.swift | 17 +++++++++---- .../Services/BasePassCodeService.swift | 25 ++++++++----------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 21d7877..5d45e8c 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -76,11 +76,22 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController initialLoadView() initialDotNumberConfiguration() - enebleKeyboard() configureBackgroundNotifications() showTouchIdIfNeeded(with: touchIdHint) } + override open func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + fakeTextField.becomeFirstResponder() + } + + override open func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + fakeTextField.resignFirstResponder() + } + // MARK: - Private functions private func configureBackgroundNotifications() { @@ -95,10 +106,6 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController .disposed(by: disposeBag) } - private func enebleKeyboard() { - fakeTextField.becomeFirstResponder() - } - private func initialDotNumberConfiguration() { dotStackView.arrangedSubviews.forEach { dotStackView.removeArrangedSubview($0) } diff --git a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift index 5892a7c..53ce561 100644 --- a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift +++ b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift @@ -28,7 +28,7 @@ import IDZSwiftCommonCrypto open class BasePassCodeService { /// Override to set specific keychain service name - open class var keychainService: String { + open class var keychainServiceString: String { return Bundle.main.bundleIdentifier ?? "" } @@ -42,37 +42,34 @@ open class BasePassCodeService { // MARK: - Private stuff - fileprivate lazy var keychain: Keychain = { - return Keychain(service: BasePassCodeService.keychainService) - .synchronizable(false) - }() + private lazy var keychain = Keychain(service: BasePassCodeService.keychainServiceString).synchronizable(false) - fileprivate var passCodeHash: String? { + private var passCodeHash: String? { return keychain[Keys.passCodeHash] } - fileprivate enum Keys { + private enum Keys { static let passCodeHash = "passCodeHash" static let isTouchIdEnabled = "isTouchIdEnabled" static let isInitialLoad = "isInitialLoad" } - fileprivate enum Values { + private enum Values { static let touchIdEnabled = "touchIdEnabled" static let initialLoad = "initialLoad" } } -extension BasePassCodeService { +public extension BasePassCodeService { /// Indicates is pass code already saved on this device - public var isPassCodeSaved: Bool { + var isPassCodeSaved: Bool { return keychain[Keys.passCodeHash] != nil } /// Indicates is it possible to authenticate on this device via touch id - public var isTouchIdEnabled: Bool { + var isTouchIdEnabled: Bool { get { return keychain[Keys.isTouchIdEnabled] == Values.touchIdEnabled } @@ -82,7 +79,7 @@ extension BasePassCodeService { } /// Saves new pass code - public func save(passCode: String?) { + func save(passCode: String?) { if let passCode = passCode { keychain[Keys.passCodeHash] = sha256(passCode) } else { @@ -91,12 +88,12 @@ extension BasePassCodeService { } /// Check if pass code is correct - public func check(passCode: String) -> Bool { + func check(passCode: String) -> Bool { return sha256(passCode) == passCodeHash } /// Reset pass code settings - public func reset() { + func reset() { save(passCode: nil) isTouchIdEnabled = false } From 7b6e73e789c3422f592d05c22451164c17d0c277 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 23 Mar 2018 15:21:12 +0300 Subject: [PATCH 04/12] Update name & refactor error --- .../Sources/Classes/ApiResponse.swift | 2 +- .../Sources/Classes/BaseDateFormatter.swift | 2 +- .../Sources/Classes/LoadingBarButton.swift | 2 +- .../Model/PassCodeConfiguration.swift | 2 +- .../PassCode/Model/PassCodeError.swift | 2 +- .../PassCode/Model/PassCodeHolder.swift | 8 +++---- .../Model/PassCodeHolderProtocol.swift | 2 +- .../Model/PassCodeValidationResult.swift | 22 ++++++++++--------- .../ViewModel/BasePassCodeViewModel.swift | 6 ++--- LeadKitAdditions/Sources/Enums/ApiError.swift | 2 +- .../Sources/Enums/ApiErrorProtocol.swift | 2 +- .../Extensions/Observable+Extensions.swift | 2 +- .../UIBarButtonItem+Extensions.swift | 2 +- .../Extensions/UserDefaults+UserService.swift | 2 +- .../Services/BasePassCodeService.swift | 2 +- .../Sources/Services/BaseUserService.swift | 2 +- .../Services/Network/ApiNetworkService.swift | 2 +- ...aultNetworkService+ActivityIndicator.swift | 2 +- .../Network/DefaultNetworkService.swift | 2 +- .../Sources/Services/TouchIDService.swift | 2 +- 20 files changed, 36 insertions(+), 34 deletions(-) diff --git a/LeadKitAdditions/Sources/Classes/ApiResponse.swift b/LeadKitAdditions/Sources/Classes/ApiResponse.swift index 98773b5..6a98860 100644 --- a/LeadKitAdditions/Sources/Classes/ApiResponse.swift +++ b/LeadKitAdditions/Sources/Classes/ApiResponse.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Classes/BaseDateFormatter.swift b/LeadKitAdditions/Sources/Classes/BaseDateFormatter.swift index 3bdf9ae..cec812c 100644 --- a/LeadKitAdditions/Sources/Classes/BaseDateFormatter.swift +++ b/LeadKitAdditions/Sources/Classes/BaseDateFormatter.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Classes/LoadingBarButton.swift b/LeadKitAdditions/Sources/Classes/LoadingBarButton.swift index 2d7a7a9..5db8b52 100644 --- a/LeadKitAdditions/Sources/Classes/LoadingBarButton.swift +++ b/LeadKitAdditions/Sources/Classes/LoadingBarButton.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift index a8b5931..4d9bc18 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeConfiguration.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift index 6e766af..64b3de4 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolder.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolder.swift index 4dae8fc..aac5919 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolder.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolder.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal @@ -81,7 +81,7 @@ public class PassCodeHolderCreate: PassCodeHolderProtocol { if let passCode = passCode { return .valid(passCode) } else { - return .inValid(.codesNotMatch) + return .invalid(.codesNotMatch) } } @@ -112,7 +112,7 @@ public class PassCodeHolderEnter: PassCodeHolderProtocol { if let passCode = passCode { return .valid(passCode) } else { - return .inValid(nil) + return .invalid(nil) } } @@ -178,7 +178,7 @@ public class PassCodeHolderChange: PassCodeHolderProtocol { if let passCode = passCode { return .valid(passCode) } else { - return .inValid(enterStep == .newEnter ? nil : .codesNotMatch) + return .invalid(enterStep == .newEnter ? nil : .codesNotMatch) } } diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift index b4a031d..d8bcf6c 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeHolderProtocol.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift index 41bdbd1..1cede03 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal @@ -24,33 +24,35 @@ public enum PassCodeValidationResult { case valid(String) - case inValid(PassCodeError?) + case invalid(PassCodeError?) - public var isValid: Bool { +} + +public extension PassCodeValidationResult { + var isValid: Bool { switch self { case .valid: return true - default: + case .invalid(_): return false } } - public var passCode: String? { + var passCode: String? { switch self { case let .valid(passCode): return passCode - default: + case .invalid(_): return nil } } - public var error: PassCodeError? { + var error: PassCodeError? { switch self { - case let .inValid(error): + case let .invalid(error): return error - default: + case .valid(_): return nil } } - } diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index b024f41..2e4245a 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal @@ -180,12 +180,12 @@ extension BasePassCodeViewModel { attemptsNumber += 1 if let passCode = validationResult.passCode, !isEnteredPassCodeValid(passCode) { - validationResult = .inValid(.wrongCode) + validationResult = .invalid(.wrongCode) } if (!validationResult.isValid && attemptsNumber == Int(passCodeConfiguration.maxAttemptsNumber)) || attemptsNumber > Int(passCodeConfiguration.maxAttemptsNumber) { - validationResult = .inValid(.tooManyAttempts) + validationResult = .invalid(.tooManyAttempts) } } diff --git a/LeadKitAdditions/Sources/Enums/ApiError.swift b/LeadKitAdditions/Sources/Enums/ApiError.swift index bb4533e..aff43d1 100644 --- a/LeadKitAdditions/Sources/Enums/ApiError.swift +++ b/LeadKitAdditions/Sources/Enums/ApiError.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Enums/ApiErrorProtocol.swift b/LeadKitAdditions/Sources/Enums/ApiErrorProtocol.swift index 31b0113..f94a9a8 100644 --- a/LeadKitAdditions/Sources/Enums/ApiErrorProtocol.swift +++ b/LeadKitAdditions/Sources/Enums/ApiErrorProtocol.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Extensions/Observable+Extensions.swift b/LeadKitAdditions/Sources/Extensions/Observable+Extensions.swift index c6dbe09..c854ee9 100644 --- a/LeadKitAdditions/Sources/Extensions/Observable+Extensions.swift +++ b/LeadKitAdditions/Sources/Extensions/Observable+Extensions.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Extensions/UIBarButtonItem+Extensions.swift b/LeadKitAdditions/Sources/Extensions/UIBarButtonItem+Extensions.swift index ef3eaf7..f237bf2 100644 --- a/LeadKitAdditions/Sources/Extensions/UIBarButtonItem+Extensions.swift +++ b/LeadKitAdditions/Sources/Extensions/UIBarButtonItem+Extensions.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Extensions/UserDefaults+UserService.swift b/LeadKitAdditions/Sources/Extensions/UserDefaults+UserService.swift index 6ca694f..39ffd95 100644 --- a/LeadKitAdditions/Sources/Extensions/UserDefaults+UserService.swift +++ b/LeadKitAdditions/Sources/Extensions/UserDefaults+UserService.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift index 53ce561..a7a9c67 100644 --- a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift +++ b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Services/BaseUserService.swift b/LeadKitAdditions/Sources/Services/BaseUserService.swift index 016b749..2fa1606 100644 --- a/LeadKitAdditions/Sources/Services/BaseUserService.swift +++ b/LeadKitAdditions/Sources/Services/BaseUserService.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Services/Network/ApiNetworkService.swift b/LeadKitAdditions/Sources/Services/Network/ApiNetworkService.swift index 2293906..f30065f 100644 --- a/LeadKitAdditions/Sources/Services/Network/ApiNetworkService.swift +++ b/LeadKitAdditions/Sources/Services/Network/ApiNetworkService.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService+ActivityIndicator.swift b/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService+ActivityIndicator.swift index abe2e32..28f5aa1 100644 --- a/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService+ActivityIndicator.swift +++ b/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService+ActivityIndicator.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService.swift b/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService.swift index 54d8c2f..b64d9c0 100644 --- a/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService.swift +++ b/LeadKitAdditions/Sources/Services/Network/DefaultNetworkService.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal diff --git a/LeadKitAdditions/Sources/Services/TouchIDService.swift b/LeadKitAdditions/Sources/Services/TouchIDService.swift index 4dfaab2..69e6325 100644 --- a/LeadKitAdditions/Sources/Services/TouchIDService.swift +++ b/LeadKitAdditions/Sources/Services/TouchIDService.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Touch Instinct +// Copyright (c) 2018 Touch Instinct // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the Software), to deal From 27f42e55a1dbb10f8fdaa475b31d29cc3a913e47 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 23 Mar 2018 15:52:34 +0300 Subject: [PATCH 05/12] Rename to biometrics --- .../View/BasePassCodeViewController.swift | 6 ++-- .../ViewModel/BasePassCodeViewModel.swift | 14 ++++----- .../Services/BasePassCodeService.swift | 30 ++++++++++--------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 5d45e8c..b246456 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -77,7 +77,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController initialLoadView() initialDotNumberConfiguration() configureBackgroundNotifications() - showTouchIdIfNeeded(with: touchIdHint) + showBiometricsRequestIfNeeded(with: touchIdHint) } override open func viewWillAppear(_ animated: Bool) { @@ -149,8 +149,8 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController } } - private func showTouchIdIfNeeded(with description: String) { - guard viewModel.isTouchIdEnabled && viewModel.controllerType == .enter else { + private func showBiometricsRequestIfNeeded(with description: String) { + guard viewModel.isBiometricsEnabled && viewModel.controllerType == .enter else { return } diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index 2e4245a..505c715 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -138,23 +138,23 @@ open class BasePassCodeViewModel: BaseViewModel { assertionFailure("You should override this method: authSucceed(_ type: PassCodeAuthType)") } - // MARK: - Functions that can you can override to use TouchId + // MARK: - Biometrics - /// Override to be able use touchId during authentication - open var isTouchIdEnabled: Bool { + /// Posibility to use biometrics for authentication + open var isBiometricsEnabled: Bool { return false } - /// You should save user choice about authenticate by touchId - open func activateTouchIdForUser() { - assertionFailure("You should override this method: activateTouchIdForUser()") + /// Notify about activation for biometrics. Remember to save user choice + open func activateBiometricsForUser() { + assertionFailure("You should override this method: activateBiometricsForUser()") } } extension BasePassCodeViewModel { - fileprivate func set(passCode: String) { + private func set(passCode: String) { passCodeHolder.add(passCode: passCode) validateIfNeeded() diff --git a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift index a7a9c67..b79d6ea 100644 --- a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift +++ b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift @@ -24,6 +24,17 @@ import KeychainAccess import CocoaLumberjack import IDZSwiftCommonCrypto +private enum Keys { + static let passCodeHash = "passCodeHashKey" + static let isBiometricsEnabled = "isBiometricsEnabledKey" + static let isInitialLoad = "isInitialLoadKey" +} + +private enum Values { + static let biometricsEnabled = "biometricsEnabled" + static let initialLoad = "initialLoad" +} + /// Represents base pass code service which encapsulates pass code storing open class BasePassCodeService { @@ -48,16 +59,7 @@ open class BasePassCodeService { return keychain[Keys.passCodeHash] } - private enum Keys { - static let passCodeHash = "passCodeHash" - static let isTouchIdEnabled = "isTouchIdEnabled" - static let isInitialLoad = "isInitialLoad" - } - private enum Values { - static let touchIdEnabled = "touchIdEnabled" - static let initialLoad = "initialLoad" - } } @@ -68,13 +70,13 @@ public extension BasePassCodeService { return keychain[Keys.passCodeHash] != nil } - /// Indicates is it possible to authenticate on this device via touch id - var isTouchIdEnabled: Bool { + /// Possibility to authenticate via biometrics. TouchID or FaceID + var isBiometricsAuthorizationEnabled: Bool { get { - return keychain[Keys.isTouchIdEnabled] == Values.touchIdEnabled + return keychain[Keys.isBiometricsEnabled] == Values.biometricsEnabled } set { - keychain[Keys.isTouchIdEnabled] = newValue ? Values.touchIdEnabled : nil + keychain[Keys.isBiometricsEnabled] = newValue ? Values.biometricsEnabled : nil } } @@ -95,7 +97,7 @@ public extension BasePassCodeService { /// Reset pass code settings func reset() { save(passCode: nil) - isTouchIdEnabled = false + isBiometricsAuthorizationEnabled = false } } From f612914307aef71f26d0386aecc0f6344ed56359 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 23 Mar 2018 16:37:03 +0300 Subject: [PATCH 06/12] Rename TouchID to biometrics --- .../View/BasePassCodeViewController.swift | 6 +---- .../ViewModel/BasePassCodeViewModel.swift | 27 +++++++++++++------ .../Services/BasePassCodeService.swift | 2 -- ...DService.swift => BiometricsService.swift} | 22 +++++++-------- 4 files changed, 29 insertions(+), 28 deletions(-) rename LeadKitAdditions/Sources/Services/{TouchIDService.swift => BiometricsService.swift} (74%) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index b246456..5830e59 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -154,11 +154,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController return } - viewModel.touchIdService?.authenticateByTouchId(description: description) { [weak self] isSuccess in - if isSuccess { - self?.viewModel.authSucceed(.touchId) - } - } + viewModel.authenticateUsingBiometrics(with: description) } private func resetUI() { diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index 505c715..eedffb5 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -37,8 +37,8 @@ open class BasePassCodeViewModel: BaseViewModel { public let disposeBag = DisposeBag() - /// TouchId service, which can answer if user is authorized by finger - public let touchIdService: TouchIDService? + /// Service that can answer if user is authorized by biometrics + public let biometricsService = BiometricsService() /// Contains configuration for pass code operations public let passCodeConfiguration: PassCodeConfiguration @@ -59,13 +59,9 @@ open class BasePassCodeViewModel: BaseViewModel { private lazy var passCodeHolder: PassCodeHolderProtocol = PassCodeHolderBuilder.build(with: self.controllerType) - public init(controllerType: PassCodeControllerType, - passCodeConfiguration: PassCodeConfiguration, - touchIdService: TouchIDService? = nil) { - + public init(controllerType: PassCodeControllerType, passCodeConfiguration: PassCodeConfiguration) { self.controllerType = controllerType self.passCodeConfiguration = passCodeConfiguration - self.touchIdService = touchIdService bindViewModel() } @@ -125,6 +121,16 @@ open class BasePassCodeViewModel: BaseViewModel { passCodeHolder.reset() } + public func authenticateUsingBiometrics(with description: String) { + biometricsService.authenticateWithBiometrics(with: description) { [weak self] success, error in + if success { + self?.authSucceed(.touchId) + } else { + self?.authFailed(with: error) + } + } + } + // MARK: - HAVE TO OVERRIDE /// Override to check if entered pass code is equal to stored @@ -133,11 +139,16 @@ open class BasePassCodeViewModel: BaseViewModel { return false } - /// Handler called after successful authentication + /// Method is called after successful authentication open func authSucceed(_ type: PassCodeAuthType) { assertionFailure("You should override this method: authSucceed(_ type: PassCodeAuthType)") } + /// Called when authentication failed + open func authFailed(with: Error?) { + assertionFailure("You should override this method: authFailed(with: Error)") + } + // MARK: - Biometrics /// Posibility to use biometrics for authentication diff --git a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift index b79d6ea..8686b1c 100644 --- a/LeadKitAdditions/Sources/Services/BasePassCodeService.swift +++ b/LeadKitAdditions/Sources/Services/BasePassCodeService.swift @@ -59,8 +59,6 @@ open class BasePassCodeService { return keychain[Keys.passCodeHash] } - - } public extension BasePassCodeService { diff --git a/LeadKitAdditions/Sources/Services/TouchIDService.swift b/LeadKitAdditions/Sources/Services/BiometricsService.swift similarity index 74% rename from LeadKitAdditions/Sources/Services/TouchIDService.swift rename to LeadKitAdditions/Sources/Services/BiometricsService.swift index 69e6325..925cb61 100644 --- a/LeadKitAdditions/Sources/Services/TouchIDService.swift +++ b/LeadKitAdditions/Sources/Services/BiometricsService.swift @@ -22,34 +22,30 @@ import LocalAuthentication -public typealias TouchIDServiceAuthHandler = (Bool) -> Void +public typealias BiometricsAuthHandler = (Bool, Error?) -> Void -/// Represents service that provides access to authentication via touch id -public class TouchIDService { +/// Service that provide access to authentication via biometric +public final class BiometricsService { - private lazy var laContext: LAContext = { - return LAContext() - }() + private lazy var laContext = LAContext() public init() {} /// Indicates is it possible to authenticate on this device via touch id - public var canAuthenticateByTouchId: Bool { + public var canAuthenticateWithBiometrics: Bool { return laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) } /** - Initiates system touch id authentication process + Initiates system biometrics authentication process - parameters: - description: prompt on the system alert that describes what for user should attach finger to device - authHandler: callback, with parameter, indicates if user authenticate successfuly */ - public func authenticateByTouchId(description: String, authHandler: @escaping TouchIDServiceAuthHandler) { - laContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, - localizedReason: description) { success, _ in - - authHandler(success) + public func authenticateWithBiometrics(with description: String, authHandler: @escaping BiometricsAuthHandler) { + laContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: description) { success, error in + authHandler(success, error) } } From 8bba538e4aac95c70ca48316a5708805ab820f87 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 23 Mar 2018 17:40:19 +0300 Subject: [PATCH 07/12] Renamification & configuration --- .../View/BasePassCodeViewController.swift | 4 ++-- .../Sources/Services/BiometricsService.swift | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 5830e59..8049467 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -77,7 +77,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController initialLoadView() initialDotNumberConfiguration() configureBackgroundNotifications() - showBiometricsRequestIfNeeded(with: touchIdHint) + showBiometricsRequestIfNeeded(with: biometricsAuthorizationHint) } override open func viewWillAppear(_ animated: Bool) { @@ -165,7 +165,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController // MARK: - HAVE TO OVERRIDE /// Returns prompt that appears on touch id system alert - open var touchIdHint: String { + open var biometricsAuthorizationHint: String { assertionFailure("You should override this var: touchIdHint") return "" } diff --git a/LeadKitAdditions/Sources/Services/BiometricsService.swift b/LeadKitAdditions/Sources/Services/BiometricsService.swift index 925cb61..c22b281 100644 --- a/LeadKitAdditions/Sources/Services/BiometricsService.swift +++ b/LeadKitAdditions/Sources/Services/BiometricsService.swift @@ -24,13 +24,13 @@ import LocalAuthentication public typealias BiometricsAuthHandler = (Bool, Error?) -> Void + + /// Service that provide access to authentication via biometric public final class BiometricsService { private lazy var laContext = LAContext() - public init() {} - /// Indicates is it possible to authenticate on this device via touch id public var canAuthenticateWithBiometrics: Bool { return laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) @@ -43,7 +43,17 @@ public final class BiometricsService { - description: prompt on the system alert that describes what for user should attach finger to device - authHandler: callback, with parameter, indicates if user authenticate successfuly */ - public func authenticateWithBiometrics(with description: String, authHandler: @escaping BiometricsAuthHandler) { + public func authenticateWithBiometrics(with description: String, + fallback fallbackTitle: String? = nil, + cancel cancelTitle: String? = nil, + authHandler: @escaping BiometricsAuthHandler) { + if #available(iOS 10.0, *), let cancel = cancelTitle { + laContext.localizedCancelTitle = cancelTitle + } + if let fallback = fallbackTitle { + laContext.localizedFallbackTitle = fallbackTitle + } + laContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: description) { success, error in authHandler(success, error) } From 9baa92a303b08f355e520629709c1a8632d9c5c4 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 23 Mar 2018 20:00:46 +0300 Subject: [PATCH 08/12] Add attempt index --- .../PassCode/Model/PassCodeError.swift | 16 +++++- .../View/BasePassCodeViewController.swift | 4 +- .../ViewModel/BasePassCodeViewModel.swift | 53 ++++++++++--------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift index 64b3de4..ca7ebed 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeError.swift @@ -21,8 +21,22 @@ // /// Describes error, which may occur during pass code entering +/// - codesNotMatch: Different codes +/// - wrongCode: Value is remaining attemps +/// - tooManyAttempts: Attempts limit reached public enum PassCodeError: Error { case codesNotMatch - case wrongCode + case wrongCode(Int) case tooManyAttempts } + +public extension PassCodeError { + var isTooManyAttempts: Bool { + switch self { + case .tooManyAttempts: + return true + default: + return false + } + } +} diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 8049467..6fee439 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -226,8 +226,8 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController if validationResult.isValid { self?.hideError() - } else if let pasCodeError = validationResult.error { - self?.showError(for: pasCodeError) + } else if let passCodeError = validationResult.error { + self?.showError(for: passCodeError) } }) .disposed(by: disposeBag) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index eedffb5..b64955d 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -77,29 +77,8 @@ open class BasePassCodeViewModel: BaseViewModel { }) .disposed(by: disposeBag) - validationResultHolder.asDriver() - .drive(onNext: { [weak self] validationResult in - guard let sSelf = self else { - return - } - - if sSelf.passCodeHolder.type == .change { - if validationResult?.isValid ?? false, - sSelf.passCodeHolder.enterStep == .repeatEnter, - let passCode = validationResult?.passCode { - - sSelf.authSucceed(.passCode(passCode)) - } else { - sSelf.passCodeControllerStateHolder.value = sSelf.passCodeHolder.enterStep - } - } else { - if validationResult?.isValid ?? false, let passCode = validationResult?.passCode { - sSelf.authSucceed(.passCode(passCode)) - } else { - sSelf.passCodeControllerStateHolder.value = sSelf.passCodeHolder.enterStep - } - } - }) + validationResultHolder.asObservable() + .bind(to: validationResultBinder) .disposed(by: disposeBag) } @@ -163,6 +142,29 @@ open class BasePassCodeViewModel: BaseViewModel { } +private extension BasePassCodeViewModel { + var validationResultBinder: Binder { + return Binder(self) { model, validationResult in + let isValid = validationResult?.isValid ?? false + let passCode = validationResult?.passCode + + if model.passCodeHolder.type == .change { + if isValid, model.passCodeHolder.enterStep == .repeatEnter, let passCode = passCode { + model.authSucceed(.passCode(passCode)) + } else { + model.passCodeControllerStateHolder.value = model.passCodeHolder.enterStep + } + } else { + if isValid, let passCode = passCode { + model.authSucceed(.passCode(passCode)) + } else { + model.passCodeControllerStateHolder.value = model.passCodeHolder.enterStep + } + } + } + } +} + extension BasePassCodeViewModel { private func set(passCode: String) { @@ -177,7 +179,7 @@ extension BasePassCodeViewModel { private var shouldUpdateControllerState: Bool { return !passCodeHolder.shouldValidate || !(validationResultHolder.value?.isValid ?? true) || - validationResultHolder.value?.error == .tooManyAttempts + validationResultHolder.value?.error?.isTooManyAttempts ?? false } private func validateIfNeeded() { @@ -191,7 +193,8 @@ extension BasePassCodeViewModel { attemptsNumber += 1 if let passCode = validationResult.passCode, !isEnteredPassCodeValid(passCode) { - validationResult = .invalid(.wrongCode) + assert(passCodeConfiguration.maxAttemptsNumber > attemptsNumber) + validationResult = .invalid(.wrongCode(passCodeConfiguration.maxAttemptsNumber - attemptsNumber)) } if (!validationResult.isValid && attemptsNumber == Int(passCodeConfiguration.maxAttemptsNumber)) || From 5d9a456d1d882dce503a3cc928cad3e567d18f35 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Mon, 26 Mar 2018 13:33:04 +0300 Subject: [PATCH 09/12] Code review notes --- .../PassCode/Model/PassCodeValidationResult.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift index 1cede03..f918a6d 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/Model/PassCodeValidationResult.swift @@ -33,7 +33,7 @@ public extension PassCodeValidationResult { switch self { case .valid: return true - case .invalid(_): + case .invalid: return false } } @@ -42,7 +42,7 @@ public extension PassCodeValidationResult { switch self { case let .valid(passCode): return passCode - case .invalid(_): + case .invalid: return nil } } @@ -51,7 +51,7 @@ public extension PassCodeValidationResult { switch self { case let .invalid(error): return error - case .valid(_): + case .valid: return nil } } From e602c1db599e765aaf01e2cdc48b50bf488441cf Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Mon, 26 Mar 2018 14:11:46 +0300 Subject: [PATCH 10/12] Update logic --- .../View/BasePassCodeViewController.swift | 8 ++++---- .../ViewModel/BasePassCodeViewModel.swift | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 6fee439..e441d32 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -177,9 +177,9 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController } /// Override to change error description - open func errorDescription(for error: PassCodeError) -> String { + open func errorDescription(for error: PassCodeError) -> NSAttributedString? { assertionFailure("You should override this method: errorDescription(for error: PassCodeError)") - return "" + return nil } /// Override to change action title text @@ -192,7 +192,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController /// Call to show error open func showError(for error: PassCodeError) { - errorLabel?.text = errorDescription(for: error) + errorLabel?.attributedText = errorDescription(for: error) errorLabel?.isHidden = false } @@ -232,7 +232,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController }) .disposed(by: disposeBag) - viewModel.passCodeControllerState + viewModel.passCodeControllerStateDriver .drive(onNext: { [weak self] controllerState in self?.configureUI(for: controllerState) }) diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index b64955d..68952ff 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -48,9 +48,9 @@ open class BasePassCodeViewModel: BaseViewModel { return validationResultHolder.asDriver() } - private let passCodeControllerStateHolder = Variable(.enter) - public var passCodeControllerState: Driver { - return passCodeControllerStateHolder.asDriver() + private let passCodeControllerStateVariable = Variable(.enter) + public var passCodeControllerStateDriver: Driver { + return passCodeControllerStateVariable.asDriver() } private let passCodeText = Variable(nil) @@ -95,7 +95,7 @@ open class BasePassCodeViewModel: BaseViewModel { public func reset() { passCodeText.value = nil validationResultHolder.value = nil - passCodeControllerStateHolder.value = controllerType == .change ? .oldEnter : .enter + passCodeControllerStateVariable.value = controllerType == .change ? .oldEnter : .enter attemptsNumber = 0 passCodeHolder.reset() } @@ -152,13 +152,13 @@ private extension BasePassCodeViewModel { if isValid, model.passCodeHolder.enterStep == .repeatEnter, let passCode = passCode { model.authSucceed(.passCode(passCode)) } else { - model.passCodeControllerStateHolder.value = model.passCodeHolder.enterStep + model.passCodeControllerStateVariable.value = model.passCodeHolder.enterStep } } else { if isValid, let passCode = passCode { model.authSucceed(.passCode(passCode)) } else { - model.passCodeControllerStateHolder.value = model.passCodeHolder.enterStep + model.passCodeControllerStateVariable.value = model.passCodeHolder.enterStep } } } @@ -172,7 +172,7 @@ extension BasePassCodeViewModel { validateIfNeeded() if shouldUpdateControllerState { - passCodeControllerStateHolder.value = passCodeHolder.enterStep + passCodeControllerStateVariable.value = passCodeHolder.enterStep } } @@ -189,11 +189,12 @@ extension BasePassCodeViewModel { var validationResult = passCodeHolder.validate() - if passCodeHolder.type == .enter || (passCodeHolder.type == .change && passCodeHolder.enterStep == .newEnter) { + let passCodeValidationForPassCodeChange = passCodeHolder.type == .change && passCodeHolder.enterStep == .newEnter + + if passCodeHolder.type == .enter || passCodeValidationForPassCodeChange { attemptsNumber += 1 if let passCode = validationResult.passCode, !isEnteredPassCodeValid(passCode) { - assert(passCodeConfiguration.maxAttemptsNumber > attemptsNumber) validationResult = .invalid(.wrongCode(passCodeConfiguration.maxAttemptsNumber - attemptsNumber)) } From d91a81b2252cb7b1db7723e61e3a3dc4064d941c Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Mon, 26 Mar 2018 16:48:05 +0300 Subject: [PATCH 11/12] Remove empty lines --- LeadKitAdditions/Sources/Services/BiometricsService.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/LeadKitAdditions/Sources/Services/BiometricsService.swift b/LeadKitAdditions/Sources/Services/BiometricsService.swift index c22b281..034ac89 100644 --- a/LeadKitAdditions/Sources/Services/BiometricsService.swift +++ b/LeadKitAdditions/Sources/Services/BiometricsService.swift @@ -24,8 +24,6 @@ import LocalAuthentication public typealias BiometricsAuthHandler = (Bool, Error?) -> Void - - /// Service that provide access to authentication via biometric public final class BiometricsService { From 1b26dd25bd324a53909ef6b37e42337eb94193c0 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Mon, 26 Mar 2018 16:49:37 +0300 Subject: [PATCH 12/12] Update podspec --- CHANGELOG.md | 3 +++ LeadKitAdditions.podspec | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7025f68..01bd1ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.1.4 +- **Update**: Refactor PassCode + ## 0.1.3 - **Update**: Typical api response keys naming diff --git a/LeadKitAdditions.podspec b/LeadKitAdditions.podspec index c015803..91d2b7a 100644 --- a/LeadKitAdditions.podspec +++ b/LeadKitAdditions.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LeadKitAdditions" - s.version = "0.1.3" + s.version = "0.1.4" s.summary = "iOS framework with a bunch of tools for rapid development" s.homepage = "https://github.com/TouchInstinct/LeadKitAdditions" s.license = "Apache License, Version 2.0"