在我的真实iPhoneX设备上运行提供的代码(由ViewController中的按钮触发的简单IBAction),我无法通过评估FaceID失败而陷入评估策略的错误情况: LAError.authenticationFailed 认可更多次。这种情况在代码中由函数validatePolicyErrorMessage()进行管理。
相反,我可以使用 Hardware-> FaceID-> Non-matching Face 选择3倍的 Hardware-> FaceID-> Non-matching Face ,使其成为 LAError.authenticationFailed 再次”警报,但完全没有轻敲警报本身上的“再次尝试FaceID”按钮:只需重复选择3次硬件-> FaceID->不匹配的面孔
有人可以建议我我的代码出了什么问题吗?非常抱歉,但是我尝试匹配所有可能的情况和子情况。
这里是此项目的链接: https://github.com/giurobrossi/testBiometricAuthentication.git
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func authButton(_ sender: Any) {
let context = LAContext()
if #available(iOS 10, *) {
context.localizedCancelTitle = "Cancel"
}
var canEvaluateError: NSError?
var message = ""
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &canEvaluateError) {
if #available(iOS 11.0, *) {
switch context.biometryType.rawValue {
case 0:
message = "Device doesn't have a biometry available"
case 1:
message = "Device has got TouchID"
case 2:
message = "Device has got FaceID"
default:
message = "biometry device not recognized"
}
} else {
message = "Device is eligible to evaluate the authentication. (iOS < 11)"
}
//self.presentAlertMainThread(message: message)
print(message)
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Let's authenticate!" ) { success, evaluateError in
if success {
self.presentAlertMainThread(message: "Login succesful !")
}
else {
message = self.evaluatePolicyErrorMessage(errorCode: (evaluateError! as NSError).code)
self.presentAlertMainThread(message: message )
print("EvaluatePolicy Error: \(evaluateError!._code)")
}
}
}
else {
message = canEvaluatePolicyErrorMessage(errorCode: (canEvaluateError?.code)!, context: context)
self.presentAlertMainThread(message: message)
print("CanEvaluatePolicy Error: \(String(describing: canEvaluateError?.code ))")
}
}
}
extension ViewController {
func presentAlertMainThread(message: String) {
DispatchQueue.main.async(execute: {
let alertController = UIAlertController(title: "Attenzione", message: message, preferredStyle: UIAlertControllerStyle.alert)
self.present(alertController, animated: true, completion: nil)
let defaultAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)
alertController.addAction(defaultAction)
})
}
func canEvaluatePolicyErrorMessage(errorCode: Int, context: LAContext) -> String {
var message = ""
if #available(iOS 11.0, *) {
switch errorCode {
// -6
case LAError.biometryNotAvailable.rawValue:
switch context.biometryType.rawValue {
case 0: // non capita mail (iOS >= 11)
message = "Device does not have any biometry available"
case 1:
message = "Device has got TouchID but the permission is false"
case 2:
message = "Device has got FaceID but the permission is false"
default:
message = "biometry sensor not recognized"
}
// TBD
case LAError.biometryLockout.rawValue:
switch context.biometryType.rawValue {
case 0:
message = "Device does not have any biometry available"
case 1:
message = "Device has got TouchID but the biometry is locked"
case 2:
message = "Device has got FaceID but the biometry is locked"
default:
message = "biometry sensor not recognized"
}
// -7
case LAError.biometryNotEnrolled.rawValue:
switch context.biometryType.rawValue {
case 0:
message = "Device does not have any biometry available"
case 1:
message = "Device has got TouchID but the biometry is not enrolled"
case 2:
message = "Device has got FaceID but the biometry is not enrolled"
default:
message = "biometry sensor not recognized"
}
default:
message = "Policy Error type not managed."
}
}
else if #available(iOS 9.0, *) {
switch errorCode {
// TBD
case LAError.touchIDLockout.rawValue:
if #available(iOS 11.0, *) {
switch context.biometryType.rawValue {
case 0:
message = "Device does not have any biometry available"
case 1:
message = "Device has got TouchID but the biometry is locked"
case 2:
message = "Device has got FaceID but the biometry is locked"
default:
message = "biometry sensor not recognized"
}
} else {
message = "Too much auth. attempts by TouchID (9.0 <= iOS < 11.0) - Auth. Blocked"
}
// -6
case LAError.touchIDNotAvailable.rawValue:
if #available(iOS 11.0, *) {
switch context.biometryType.rawValue {
case 0:
message = "Device does not have any biometry available"
case 1:
message = "Device has got TouchID but the permission is false"
case 2:
message = "Device has got FaceID but the permission is false"
default:
message = "biometry sensor not recognized"
}
} else {
message = "Device does not have TouchID available (9.0 <= iOS < 11.0)"
}
// -7
case LAError.touchIDNotEnrolled.rawValue:
if #available(iOS 11.0, *) {
switch context.biometryType.rawValue {
case 0:
message = "Device does not have any biometry available"
case 1:
message = "Device has got TouchID but the biometry is not enrolled"
case 2:
message = "Device has got FaceID but the biometry is not enrolled"
default:
message = "biometry sensor not recognized"
}
} else {
message = "TouchID not 'enrolled' (9.0 <= iOS < 11.0)"
}
default:
message = "Policy Error type not managed."
}
}
else {
// 8.0 <= iOS < 9.0
print("canEvaluatePolicy Error: \(errorCode.description)")
}
return message;
}
func evaluatePolicyErrorMessage(errorCode: Int) -> String {
var message = ""
if #available(iOS 9.0, *) {
switch errorCode {
// -1
case LAError.authenticationFailed.rawValue:
message = "Authentication Failed"
// -9
case LAError.appCancel.rawValue:
message = "Authentication cancelled by the app"
// TBD
case LAError.invalidContext.rawValue:
message = "LAContext passed to this call has been previously invalidated"
// TBD
case LAError.notInteractive.rawValue:
message = "Authentication failed, because it would require showing UI which has been forbidden by using interactionNotAllowed property"
// TBD
case LAError.passcodeNotSet.rawValue:
message = "Passcode not set"
// -4
case LAError.systemCancel.rawValue:
message = "Authentication cancelled by iOS"
// -2
case LAError.userCancel.rawValue:
message = "Authentication cancelled by the user"
// -3
case LAError.userFallback.rawValue:
message = "Fallback selected by the user
default:
message = "Error not managed"
}
} else {
message = "Failed Authentication (8.0 <= iOS < 9.0) - Code: \(errorCode.description)"
}
return message
}
}