当我们被告知 Touch ID/Face ID 是否成功时,它可能不在主线程上。这意味着我们需要使用 async() 来确保我们在主线程上执行任何用户界面代码。
任务 1 的工作由 LAContext 类的 canEvaluatePolicy() 方法完成,请求安全策略类型 .deviceOwnerAuthenticationWithBiometrics。任务 2 的工作由同一个类的 evaluatePolicy() 完成,使用相同的策略类型,但它接受一个尾随闭包,告诉我们策略评估的结果:是否成功,如果不成功,原因是什么?
正如我所说,所有这些都是由本地身份验证框架提供的,因此我们需要做的第一件事就是导入该框架。在导入 UIKit 上面添加:
import LocalAuthentication
现在这是 authenticateTapped() 方法的新代码。我们已经了解了它的作用,所以这不足为奇:
@IBAction func authenticateTapped(_ sender: Any) {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Identify yourself!"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
[weak self] success, authenticationError in
DispatchQueue.main.async {
if success {
self?.unlockSecretMessage()
} else {
// error
}
}
}
} else {
// no biometry
}
}
要捕获身份验证失败错误,请将 // 错误注释替换为:
let ac = UIAlertController(title: "Authentication failed", message: "You could not be verified; please try again.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
self.present(ac, animated: true)
如果生物识别不可用,我们还需要显示错误,因此将 // no Touch ID 注释替换为:
let ac = UIAlertController(title: "Biometry unavailable", message: "Your device is not configured for biometric authentication.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
self.present(ac, animated: true)