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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46887547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:35:28  来源:igfitidea点击:

How to programmatically check support of 'Face Id' and 'Touch Id'

iosios11touch-idface-idlocalauthentication

提问by Krunal

I've integrated LocalAuthenticationfor my app security purpose, which has been supporting 'Touch Id'based supporting. But now, apple has recently added 'Face Id'based authentication also.

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

How can I check, which type of authentication is supported by a device. Touch Id or Face Id?

如何检查设备支持哪种类型的身份验证。触控 ID 还是面容 ID?

回答by leifdan01

I've been struggling to get this to work and found that I needed to use a single instance of the LAContext and needed to call the LAContextInstance.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) before getting the biometryType. Here is my final code with support for older iOS versions:

我一直在努力让它工作,发现我需要使用 LAContext 的单个实例,并且需要在获取biometryType 之前调用LAContextInstance.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)。这是我支持旧 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
}

回答by Surjeet

With Xcode 9, Look at LocalAuthentication -> LAContext -> LABiometryType.

使用 Xcode 9,查看LocalAuthentication -> LAContext -> LABiometryType

LABiometryTypeis a enum with values as in attached image

LABiometryType是一个枚举,其值如附加图像中所示

enter image description here

在此处输入图片说明

You can check which authentication type supported by device between Touch ID and FaceID or none.

您可以在 Touch ID 和 FaceID 之间检查设备支持哪种身份验证类型或不支持。

Edit:

编辑:

Apple have updated values for this enum LABiometryType. none is deprecated now.

Apple 已更新此枚举LABiometryType 的值。现在没有被弃用

enter image description here

在此处输入图片说明

回答by Alix

As I am a big fan of extension. I phrase this answer a little differently. Essense is the same. This is a drop-in extension.

因为我是扩展的忠实粉丝。我对这个答案的表述略有不同。本质是一样的。这是一个插入式扩展。

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
        }
    }
}

Use like this:

像这样使用:

var currentType = LAContext().biometricType

回答by Dren

Here is one more way via the property (for example, on your access instance).

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

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
        }
    }
}

回答by karim

Objective C :)

目标 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;
    }
}

回答by Vinayak Pal

I made a singleton class for local authentication as it helps to initialise an instance one time using staticproperty for the entire application.

我为本地身份验证创建了一个单例类,因为它有助于使用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
        }
    }
}

Implementation:

执行:

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")
        }
 }

回答by Usman Awan

Face IDis available from iOS 11 and iPhone X comes with iOS 11 by default. In the LocalAuth framework they have added a 'biometryType' property which can give you ability to detect whether Face ID is available on device.

面容 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
}

回答by Markicevic

Here is my "helper class", it includes passcode also

这是我的“助手类”,它还包括密码

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
        }
    }
}

回答by Everton Cunha

From @Markicevic extension, but ignoring cases where user is not enrolled, etc...

来自@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
    }
}

}

}

回答by Victor Bogdan

This code builds without warnings on Xcode 9.2-9.4(see comments for 9.1):

此代码在 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
}