如何以编程方式检查“Face Id”和“Touch Id”的支持

我已经为我的应用程序安全目的集成了LocalAuthentication ,它一直支持基于“Touch Id”的支持。 但是现在,苹果最近还添加了基于身份识别的身份validation。

如何检查设备支持哪种类型的身份validation。 触摸ID或面部ID?

使用Xcode 9,查看LocalAuthentication – > LAContext – > LABiometryType 。

LABiometryType是一个枚举,其值与附加图像中的值相同

在此处输入图像描述

您可以在Touch ID和FaceID之间检查设备支持的身份validation类型,或者不检查。

编辑:

Apple已更新此枚举LABiometryType的值。 none现在已弃用

在此处输入图像描述

我一直在努力让这个工作,并发现我需要使用LAContext的单个实例,并且需要在获取 biometryType之前调用LAContextInstance .canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,error:nil)。 这是我的最终代码,支持旧的iOS版本:

 static func biometricType() -> BiometricType { let authContext = LAContext() if #available(iOS 11, *) { let _ = authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) switch(authContext.biometryType) { case .none: return .none case .touchID: return .touch case .faceID: return .face } } else { return authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touch : .none } } enum BiometricType { case none case touch case face } 

这是通过属性的另一种方式(例如,在您的访问实例上)。

 import LocalAuthentication enum BiometricType { case none case touchID case faceID } var biometricType: BiometricType { get { let context = LAContext() var error: NSError? guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else { print(error?.localizedDescription ?? "") return .none } if #available(iOS 11.0, *) { switch context.biometryType { case .none: return .none case .typeTouchID: return .touchID case .typeFaceID: return .faceID } } else { return .touchID } } } 

目标C 🙂

 /** Only interesting devices are enumerated here. To change view constraints depending on screen height. Or the top notch for iPhone X */ typedef NS_ENUM(NSUInteger, BPDeviceType) { BPDeviceTypeUnknown, BPDeviceTypeiPhone4, BPDeviceTypeiPhone5, BPDeviceTypeiPhone6, BPDeviceTypeiPhone6Plus, BPDeviceTypeiPhone7, BPDeviceTypeiPhone7Plus, BPDeviceTypeiPhoneX, BPDeviceTypeiPad }; + (BPDeviceType)getDeviceType { double screenHeight = [[UIScreen mainScreen] bounds].size.height; if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad) { return BPDeviceTypeiPad; } else if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone) { if (@available(iOS 11, *)) { UIEdgeInsets insets = [UIApplication sharedApplication].delegate.window.safeAreaInsets; if (insets.top > 0) { return BPDeviceTypeiPhoneX; } } if(screenHeight == 480) { return BPDeviceTypeiPhone4; } else if (screenHeight == 568) { return BPDeviceTypeiPhone5; } else if (screenHeight == 667) { return BPDeviceTypeiPhone6; } else if (screenHeight == 736) { return BPDeviceTypeiPhone6Plus; } } return BPDeviceTypeUnknown; } + (BOOL) isBiometricIDAvailable { if (![LAContext class]) return NO; LAContext *myContext = [[LAContext alloc] init]; NSError *authError = nil; if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) { NSLog(@"%@", [authError localizedDescription]); return NO; } return YES; } + (BOOL) isTouchIDAvailable { if (![LAContext class]) return NO; LAContext *myContext = [[LAContext alloc] init]; NSError *authError = nil; if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) { NSLog(@"%@", [authError localizedDescription]); return NO; // if (authError.code == LAErrorTouchIDNotAvailable) {} } if (@available(iOS 11.0, *)) { if (myContext.biometryType == LABiometryTypeTouchID){ return YES; } else { return NO; } } else { return YES; } } + (BOOL) supportFaceID { return [BPDeviceInfo getDeviceType] == BPDeviceTypeiPhoneX; } + (BOOL) isFaceIDAvailable { if (![LAContext class]) return NO; LAContext *myContext = [[LAContext alloc] init]; NSError *authError = nil; if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) { NSLog(@"%@", [authError localizedDescription]); return NO; } if (@available(iOS 11.0, *)) { if (myContext.biometryType == LABiometryTypeFaceID){ return YES; } else { return NO; } } else { return NO; } } 

因为我是扩展的忠实粉丝。 我对这个答案的说法略有不同。 Essense是一样的。 这是一个插入式扩展。

 import LocalAuthentication extension LAContext { enum BiometricType: String { case none case touchID case faceID } var biometricType: BiometricType { var error: NSError? guard self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else { // Capture these recoverable error thru Crashlytics return .none } if #available(iOS 11.0, *) { switch self.biometryType { case .none: return .none case .touchID: return .touchID case .faceID: return .faceID } } else { return self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none } } } 

使用这样:

 var currentType = LAContext().biometricType 

此代码在Xcode 9.29.4上没有警告的情况下构建(参见9.1注释):

 @objc let biometricsAuthPolicy = LAPolicy.deviceOwnerAuthenticationWithBiometrics @objc func supportsFaceID() -> Bool { if #available(iOS 11.0, *) { return biometryType() == .faceID // return biometryType() == .typeFaceID for Xcode 9.1 } return false } @objc func supportsTouchID() -> Bool { if #available(iOS 11.0, *) { return biometryType() == .touchID // return biometryType() == .typeTouchID for Xcode 9.1 } let context = LAContext() return context.canEvaluatePolicy(biometricsAuthPolicy, error: nil) } @objc @available(iOS 11.0, *) func biometryType() -> LABiometryType { var error: NSError? let context = LAContext() guard context.canEvaluatePolicy(biometricsAuthPolicy, error: &error) else { if #available(iOS 11.2, *) { return .none } return LABiometryType.LABiometryNone // return LABiometryType.none for Xcode 9.1 } return context.biometryType } 

可以从iOS 11获得Face ID ,默认情况下,iPhone X自带iOS 11。 在LocalAuth框架中,他们添加了一个’biometryType’属性,可以让您检测Face ID是否在设备上可用。

 /// checks if face id is avaiable on device func faceIDAvailable() -> Bool { if #available(iOS 11.0, *) { let context = LAContext() return (context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthentication, error: nil) && context.biometryType == .faceID) } return false }