如何以编程方式检查 'Face Id' 和 'Touch Id' 的支持
How to programmatically check support of 'Face Id' and 'Touch Id'
出于我的应用程序安全目的,我已经集成了 LocalAuthentication,它一直支持基于 'Touch Id' 的支持。但是现在,苹果最近也添加了基于 'Face Id' 的身份验证。
我如何检查设备支持哪种类型的身份验证。 Touch ID 还是 Face ID?
同Xcode9,看LocalAuthentication -> LAContext -> LABiometryType.
LABiometryType 是一个枚举,其值如附图
您可以查看设备在 Touch ID 和 FaceID 或 none 之间支持的身份验证类型。
编辑:
Apple 已更新此枚举的值 LABiometryType。 none 现已弃用。
用于检查支持的生物识别类型的扩展 Swift 5:
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 {
return .none
}
if #available(iOS 11.0, *) {
switch self.biometryType {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
@unknown default:
#warning("Handle new Biometric type")
}
}
return self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
}
}
我一直在努力让它工作,发现我需要使用 LAContext 的单个实例并且需要调用 LAContextInstance.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) 在获取 biometryType 之前。这是我支持旧 iOS 版本的最终代码:
import LocalAuthentication
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
}
}
}
Objective 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;
}
}
此代码在 Xcode 9.2
-9.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
}
面容 ID 可从 iOS 11 开始使用,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
}
因为我是扩展的忠实粉丝。我对这个答案的措辞略有不同。本质是一样的。这是一个插入式扩展。
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
这是我的"helper class",它还包括密码
enum BiometryType: String {
case none = "None"
case faceID = "Face ID"
case touchID = "Touch ID"
case passcode = "Passcode"
}
var biometryType: BiometryType {
let myContext = LAContext()
let hasAuthenticationBiometrics = myContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
let hasAuthentication = myContext.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil)
if #available(iOS 11.0, *) {
if hasAuthentication {
if hasAuthenticationBiometrics {
switch myContext.biometryType {
case .none: return .none
case .faceID: return .faceID
case .touchID: return .touchID
}
} else {
return .passcode
}
} else {
return .none
}
} else {
if hasAuthentication {
if hasAuthenticationBiometrics {
return .touchID
} else {
return .passcode
}
} else {
return .none
}
}
}
来自@Markicevic 扩展,但忽略用户未注册等情况...
extension LAContext {
enum BiometricType: String {
case none = ""
case touchID = "Touch ID"
case faceID = "Face ID"
}
static var biometricType: BiometricType {
var error: NSError?
let context = LAContext()
_ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
if error?.code == LAError.Code.touchIDNotAvailable.rawValue {
return .none
}
if #available(iOS 11.0, *) {
switch context.biometryType {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
}
} else {
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
}
}
}
我为本地身份验证制作了一个单例 class,因为它有助于为整个应用程序使用 static
属性 一次性初始化一个实例。
import Foundation
import LocalAuthentication
public class LocalAuthManager: NSObject {
public static let shared = LocalAuthManager()
private let context = LAContext()
private let reason = "Your Request Message"
private var error: NSError?
enum BiometricType: String {
case none
case touchID
case faceID
}
private override init() {
}
// check type of local authentication device currently support
var biometricType: BiometricType {
guard self.context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
return .none
}
if #available(iOS 11.0, *) {
switch context.biometryType {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
}
} else {
return self.context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) ? .touchID : .none
}
}
}
实施:
func checkAuth() {
let authType = LocalAuthManager.shared.biometricType
switch authType {
case .none:
print("Device not registered with TouchID/FaceID")
case .touchID:
print("Device support TouchID")
case .faceID:
print("Device support FaceID")
}
}
-(BOOL)faceIDAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
if (@available(iOS 11.0, *)) {
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&authError] && myContext.biometryType == LABiometryTypeFaceID) {
return true;
}
}
return false;
}
-(BOOL)touchIDAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
if (@available(iOS 11.0, *)) {
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&authError] && myContext.biometryType == LABiometryTypeTouchID) {
return true;
}
}
return false;
}
更新swift5,切换流程需要一个默认条件。
import Foundation
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 through fabric
return .none
}
if #available(iOS 11.0, *) {
switch self.biometryType {
case .touchID:
return .touchID
case .faceID:
return .faceID
default:
return .none
}
}
return self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
}
}
测试用例在下面
// need to import LocalAuthentication in the calling file
// import LocalAuthentication
let currentType = LAContext().biometricType
print("biometry type > \(currentType)")
// biometry type > touchID
如果你想在模拟器中测试,你需要注册touchId/faceId。
Simulator > Hardware > Touch ID/Face ID > Enrolled。
请参考苹果为"Logging a User into Your App with Face ID or Touch ID"提供的示例代码,这将有助于轻松理解身份验证。
Apple 示例代码 link -
https://docs-assets.developer.apple.com/published/fbfd13f4d9/LoggingAUserIntoYourAppWithFaceIDOrTouchID.zip
阅读下方示例代码的详细解释link。
https://developer.apple.com/documentation/localauthentication/logging_a_user_into_your_app_with_face_id_or_touch_id
开始在 12 Pro 上测试一些新应用,发现我发布的应用只有 Touch ID 而没有 Face ID。
我来到这里看到了所有这些,所以我开始尝试更改我的 Touch ID 代码,但我需要做的就是将隐私密钥添加到 info.plist。
资讯属性列表➕
然后向下滚动到:隐私 - Face ID 使用说明,(类型:字符串),(值:是)
太容易了
您需要在案例中添加@unknown!!!
在较新的版本中(Xcode 13...)您可能必须指定“未知”
#warning("Handle new Biometric type") 没有 return 值
import LocalAuthentication
class BiometricType{
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
@unknown default:
return .unknown
}
} else {
return authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touch : .none
}
}
enum BiometricType {
case none
case touch
case face
case unknown
}
}
出于我的应用程序安全目的,我已经集成了 LocalAuthentication,它一直支持基于 'Touch Id' 的支持。但是现在,苹果最近也添加了基于 'Face Id' 的身份验证。
我如何检查设备支持哪种类型的身份验证。 Touch ID 还是 Face ID?
同Xcode9,看LocalAuthentication -> LAContext -> LABiometryType.
LABiometryType 是一个枚举,其值如附图
您可以查看设备在 Touch ID 和 FaceID 或 none 之间支持的身份验证类型。
编辑:
Apple 已更新此枚举的值 LABiometryType。 none 现已弃用。
用于检查支持的生物识别类型的扩展 Swift 5:
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 {
return .none
}
if #available(iOS 11.0, *) {
switch self.biometryType {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
@unknown default:
#warning("Handle new Biometric type")
}
}
return self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
}
}
我一直在努力让它工作,发现我需要使用 LAContext 的单个实例并且需要调用 LAContextInstance.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) 在获取 biometryType 之前。这是我支持旧 iOS 版本的最终代码:
import LocalAuthentication
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
}
}
}
Objective 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;
}
}
此代码在 Xcode 9.2
-9.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
}
面容 ID 可从 iOS 11 开始使用,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
}
因为我是扩展的忠实粉丝。我对这个答案的措辞略有不同。本质是一样的。这是一个插入式扩展。
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
这是我的"helper class",它还包括密码
enum BiometryType: String {
case none = "None"
case faceID = "Face ID"
case touchID = "Touch ID"
case passcode = "Passcode"
}
var biometryType: BiometryType {
let myContext = LAContext()
let hasAuthenticationBiometrics = myContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
let hasAuthentication = myContext.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil)
if #available(iOS 11.0, *) {
if hasAuthentication {
if hasAuthenticationBiometrics {
switch myContext.biometryType {
case .none: return .none
case .faceID: return .faceID
case .touchID: return .touchID
}
} else {
return .passcode
}
} else {
return .none
}
} else {
if hasAuthentication {
if hasAuthenticationBiometrics {
return .touchID
} else {
return .passcode
}
} else {
return .none
}
}
}
来自@Markicevic 扩展,但忽略用户未注册等情况...
extension LAContext {
enum BiometricType: String {
case none = ""
case touchID = "Touch ID"
case faceID = "Face ID"
}
static var biometricType: BiometricType {
var error: NSError?
let context = LAContext()
_ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
if error?.code == LAError.Code.touchIDNotAvailable.rawValue {
return .none
}
if #available(iOS 11.0, *) {
switch context.biometryType {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
}
} else {
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
}
}
}
我为本地身份验证制作了一个单例 class,因为它有助于为整个应用程序使用 static
属性 一次性初始化一个实例。
import Foundation
import LocalAuthentication
public class LocalAuthManager: NSObject {
public static let shared = LocalAuthManager()
private let context = LAContext()
private let reason = "Your Request Message"
private var error: NSError?
enum BiometricType: String {
case none
case touchID
case faceID
}
private override init() {
}
// check type of local authentication device currently support
var biometricType: BiometricType {
guard self.context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
return .none
}
if #available(iOS 11.0, *) {
switch context.biometryType {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
}
} else {
return self.context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) ? .touchID : .none
}
}
}
实施:
func checkAuth() {
let authType = LocalAuthManager.shared.biometricType
switch authType {
case .none:
print("Device not registered with TouchID/FaceID")
case .touchID:
print("Device support TouchID")
case .faceID:
print("Device support FaceID")
}
}
-(BOOL)faceIDAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
if (@available(iOS 11.0, *)) {
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&authError] && myContext.biometryType == LABiometryTypeFaceID) {
return true;
}
}
return false;
}
-(BOOL)touchIDAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
if (@available(iOS 11.0, *)) {
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&authError] && myContext.biometryType == LABiometryTypeTouchID) {
return true;
}
}
return false;
}
更新swift5,切换流程需要一个默认条件。
import Foundation
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 through fabric
return .none
}
if #available(iOS 11.0, *) {
switch self.biometryType {
case .touchID:
return .touchID
case .faceID:
return .faceID
default:
return .none
}
}
return self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
}
}
测试用例在下面
// need to import LocalAuthentication in the calling file
// import LocalAuthentication
let currentType = LAContext().biometricType
print("biometry type > \(currentType)")
// biometry type > touchID
如果你想在模拟器中测试,你需要注册touchId/faceId。
Simulator > Hardware > Touch ID/Face ID > Enrolled。
请参考苹果为"Logging a User into Your App with Face ID or Touch ID"提供的示例代码,这将有助于轻松理解身份验证。
Apple 示例代码 link - https://docs-assets.developer.apple.com/published/fbfd13f4d9/LoggingAUserIntoYourAppWithFaceIDOrTouchID.zip
阅读下方示例代码的详细解释link。 https://developer.apple.com/documentation/localauthentication/logging_a_user_into_your_app_with_face_id_or_touch_id
开始在 12 Pro 上测试一些新应用,发现我发布的应用只有 Touch ID 而没有 Face ID。
我来到这里看到了所有这些,所以我开始尝试更改我的 Touch ID 代码,但我需要做的就是将隐私密钥添加到 info.plist。
资讯属性列表➕
然后向下滚动到:隐私 - Face ID 使用说明,(类型:字符串),(值:是)
太容易了
您需要在案例中添加@unknown!!!
在较新的版本中(Xcode 13...)您可能必须指定“未知”
#warning("Handle new Biometric type") 没有 return 值
import LocalAuthentication
class BiometricType{
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
@unknown default:
return .unknown
}
} else {
return authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touch : .none
}
}
enum BiometricType {
case none
case touch
case face
case unknown
}
}