-
Notifications
You must be signed in to change notification settings - Fork 0
/
Biometrics.swift
142 lines (114 loc) · 5.64 KB
/
Biometrics.swift
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
// Biometrics.swift
// How-To-Setup-Biometrics
//
// Created by Thomas Kellough on 8/5/20.
// Copyright © 2020 Thomas Kellough. All rights reserved.
//
import Foundation
import LocalAuthentication
import UIKit
// MARK: Class initialization
class Biometrics: ViewController {
var lockScreenView: UIView?
var loginButton: UIButton?
let context = LAContext()
@objc func authenticateUser() {
loginButton?.isHidden = true
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
let reason = "Please login using TouchID in order to have access to this app"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
[weak self] success, error in
DispatchQueue.main.async {
if success {
self?.lockScreenView?.removeFromSuperview()
} else {
self?.showAlertForFailedVerification()
}
}
}
} else {
showAlertForBiometryUnavailable()
}
}
}
// MARK: Biometric UIAlerts
extension Biometrics {
func showAlertForBiometryUnavailable() {
let title = "Biometry unavailable"
let message = "Your device is not configure for biometric authentication"
showAlert(title: title, message: message, completion: nil)
}
func showAlertForFailedVerification() {
let title = "Authentication failed"
let message = "Verification failed. Please try again"
showAlert(title: title, message: message, completion: { action in
self.loginButton?.isHidden = false
})
}
func showAlert(title: String, message: String, completion: ((UIAlertAction) -> Void)?) {
let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default, handler: completion))
UIApplication.topViewController()?.present(ac, animated: true, completion: nil)
}}
// MARK: UIApplication Extensions
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.windows.first?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
return controller
}
}
// MARK: Configure Lockscreen
extension Biometrics {
func showLockedScreen(backgroundColor: UIColor, logo: UIImage?, width: CGFloat, toView view: UIView) {
lockScreenView = UIView()
assert(lockScreenView != nil, "There was a problem creating the lock screen view")
lockScreenView!.translatesAutoresizingMaskIntoConstraints = false
lockScreenView!.backgroundColor = backgroundColor
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
assert(logo != nil, "Could not find image!")
imageView.image = logo!
imageView.contentMode = .scaleAspectFit
lockScreenView!.addSubview(imageView)
imageView.widthAnchor.constraint(equalTo: lockScreenView!.widthAnchor, multiplier: width).isActive = true
imageView.centerXAnchor.constraint(equalTo: lockScreenView!.centerXAnchor).isActive = true
imageView.centerYAnchor.constraint(equalTo: lockScreenView!.centerYAnchor).isActive = true
view.addSubview(lockScreenView!)
lockScreenView?.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
lockScreenView?.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
lockScreenView?.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
lockScreenView?.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
configureLoginButton(to: lockScreenView!)
}
}
// MARK: Configure loginbutton
extension Biometrics {
func configureLoginButton(to view: UIView) {
loginButton = UIButton(type: .custom)
assert(loginButton != nil, "There was a problem creating the login button")
loginButton?.backgroundColor = UIColor.systemGreen
loginButton?.layer.cornerRadius = 8
loginButton?.titleEdgeInsets = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)
loginButton?.titleLabel?.font = .preferredFont(forTextStyle: .title1)
loginButton?.translatesAutoresizingMaskIntoConstraints = false
loginButton?.setTitle("Login", for: .normal)
loginButton?.setTitleColor(.white, for: .normal)
view.addSubview(loginButton!)
loginButton?.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40).isActive = true
loginButton?.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40).isActive = true
loginButton?.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -40).isActive = true
loginButton?.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
loginButton?.addTarget(self, action: #selector(authenticateUser), for: .touchUpInside)
}
}