This repository was archived by the owner on Feb 5, 2024. It is now read-only.
forked from velikanov/SwiftPasscodeLock
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPasscodeLock.swift
More file actions
119 lines (89 loc) · 3.95 KB
/
Copy pathPasscodeLock.swift
File metadata and controls
119 lines (89 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// PasscodeLock.swift
// PasscodeLock
//
// Created by Yanko Dimitrov on 8/28/15.
// Copyright © 2015 Yanko Dimitrov. All rights reserved.
//
import Foundation
import LocalAuthentication
open class PasscodeLock: PasscodeLockType {
open weak var delegate: PasscodeLockTypeDelegate?
public let configuration: PasscodeLockConfigurationType
open var repository: PasscodeRepositoryType {
return configuration.repository
}
open var state: PasscodeLockStateType {
return lockState
}
open var isBiometricAuthAllowed: Bool {
return isBiometricAuthEnabled() && configuration.isBiometricAuthAllowed && lockState.isBiometricAuthAllowed
}
fileprivate var lockState: PasscodeLockStateType
fileprivate lazy var passcode = [String]()
public init(state: PasscodeLockStateType, configuration: PasscodeLockConfigurationType) {
precondition(configuration.passcodeLength > 0, "Passcode length sould be greather than zero.")
self.lockState = state
self.configuration = configuration
}
open func addSign(_ sign: String) {
passcode.append(sign)
delegate?.passcodeLock(self, addedSignAtIndex: passcode.count - 1)
if passcode.count >= configuration.passcodeLength {
// handles "requires exclusive access" error at Swift 4
var lockStateCopy = lockState
lockStateCopy.acceptPasscode(passcode, fromLock: self)
passcode.removeAll(keepingCapacity: true)
}
}
open func removeSign() {
guard passcode.count > 0 else { return }
passcode.removeLast()
delegate?.passcodeLock(self, removedSignAtIndex: passcode.count)
}
open func changeStateTo(_ state: PasscodeLockStateType) {
DispatchQueue.main.async { [weak self] in
guard let strongSelf = self else { return }
strongSelf.lockState = state
strongSelf.delegate?.passcodeLockDidChangeState(strongSelf)
}
}
open func authenticateWithBiometrics() {
guard isBiometricAuthAllowed else { return }
let context = LAContext()
let reason: String
if let configReason = configuration.biometricAuthReason {
reason = configReason
} else {
if #available(iOS 11, *) {
switch(context.biometryType) {
case .touchID:
reason = localizedStringFor("PasscodeLockTouchIDReason", comment: "Authentication required to proceed")
case .faceID:
reason = localizedStringFor("PasscodeLockFaceIDReason", comment: "Authentication required to proceed")
default:
reason = localizedStringFor("PasscodeLockBiometricAuthReason", comment: "Authentication required to proceed")
}
} else {
reason = localizedStringFor("PasscodeLockBiometricAuthReason", comment: "Authentication required to proceed")
}
}
context.localizedFallbackTitle = localizedStringFor("PasscodeLockBiometricAuthButton", comment: "Biometric authentication fallback button")
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
success, error in
self.handleBiometricAuthResult(success)
}
}
fileprivate func handleBiometricAuthResult(_ success: Bool) {
DispatchQueue.main.async {
if success {
EnterPasscodeState.incorrectPasscodeAttempts = 0
self.delegate?.passcodeLockDidSucceed(self)
}
}
}
fileprivate func isBiometricAuthEnabled() -> Bool {
let context = LAContext()
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
}
}