确定iOS设备是否支持TouchID而不设置密码

我目前正在开发一个iOS应用程序,允许用户使用TouchID登录应用程序,但首先他们必须首先在应用程序内设置密码。 问题是,要显示设置密码选项以启用TouchID登录,我需要检测iOS设备是否支持TouchID。

使用LAContext和canEvaluatePolicy(如此处的答案如果设备支持Touch ID ), 如果用户在其iOS设备上设置了密码 ,我可以确定当前设备是否支持TouchID。 这是我的代码片段(我使用的是Xamarin,所以它在C#中):

static bool DeviceSupportsTouchID () { if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0)) { var context = new LAContext(); NSError authError; bool touchIDSetOnDevice = context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out authError); return (touchIDSetOnDevice || (LAStatus) Convert.ToInt16(authError.Code) != LAStatus.TouchIDNotAvailable); } return false; } 

如果用户尚未设置设备密码 ,则无论设备是否实际支持TouchID,authError都将返回“ PasscodeNotSet ”错误。

如果用户的设备支持TouchID,我想在我的应用程序中始终显示TouchID选项,无论用户是否在其设备上设置了密码(我只会警告用户首先在他们的设备上设置密码)。 反之亦然,如果用户的设备不支持TouchID,我显然不想在我的应用程序中显示TouchID选项。

所以我的问题是,无论用户是否在其设备上设置了密码,是否有一种很好的方法可以始终如一地确定iOS设备是否支持TouchID?

我能想到的唯一解决方法是确定设备的体系结构(在确定iOS设备是32位还是64位时可以回答),因为只有具有64位体系结构的设备才支持TouchID。 但是,我正在寻找是否有更好的方法来做到这一点。

先谢谢! 🙂

在下面的讨论结束时,当用户未在其设备上设置密码时,暂时无法确定设备是否实际支持TouchID。

我在Apple bug记者上报告了这个TouchID漏洞。 那些想要关注这个问题的人可以在Open Radar上看到它: http : //www.openradar.me/20342024

谢谢@rckoenes输入:)

编辑

事实certificate有人已经报告了类似的问题(#18364575)。 以下是Apple对此问题的回复:

“Engineering已根据以下信息确定此问题的行为符合预期:

如果未设置密码,您将无法检测Touch ID的存在。 一旦设置了密码,canEvaluatePolicy将最终返回LAErrorTouchIDNotAvailable或LAErrorTouchIdNotEnrolled,您将能够检测Touch ID存在/状态。

如果用户在具有Touch ID的手机上禁用了密码,则他们知道他们无法使用Touch ID,因此应用无需检测Touch ID状态或推广基于Touch ID的function。

所以…… Apple的最终答案是否定的 。 🙁

注意:来自报告此内容的人的类似StackOverflow问题 – > iOS8检查设备是否具有Touch ID (想知道为什么我之前没有找到这个问题,尽管我进行了广泛的搜索……)

检测TouchID是否可用的正确方法:

 BOOL hasTouchID = NO; // if the LAContext class is available if ([LAContext class]) { LAContext *context = [LAContext new]; NSError *error = nil; hasTouchId = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]; } 

抱歉,它位于Objective-C中,您可能需要将其转换为C#。

您应该避免检查系统版本,只检查该类或方法是否可用。

我知道这是去年的一个问题,但这个解决方案并不能满足你的需求吗? (SWIFT代码)

 if #available(iOS 8.0, *) { var error: NSError? let hasTouchID = LAContext().canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) //Show the touch id option if the device has touch id hardware feature (even if the passcode is not set or touch id is not enrolled) if(hasTouchID || (error?.code != LAError.TouchIDNotAvailable.rawValue)) { touchIDContentView.hidden = false } } 

然后,当用户按下按钮以使用触摸ID登录时:

 @IBAction func loginWithTouchId() { let context = LAContext() var error: NSError? let reasonString = "Log in with Touch ID" if (context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error)) { [context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in //Has touch id. Treat the success boolean })] } else { //Then, if the user has touch id but is not enrolled or the passcode is not set, show a alert message switch error!.code{ case LAError.TouchIDNotEnrolled.rawValue: //Show alert message to inform that touch id is not enrolled break case LAError.PasscodeNotSet.rawValue: //Show alert message to inform that passcode is not set break default: // The LAError.TouchIDNotAvailable case. // Will not catch here, because if not available, the option will not visible } } } 

希望能帮助到你!

对于Objective C
它无需检查设备版本即可在所有设备上运行良好。

 - (void)canAuthenticatedByTouchID{ LAContext *myContext = [[LAContext alloc] init]; NSError *authError = nil; NSString *myLocalizedReasonString = touchIDRequestReason; if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) { }else{ switch (authError.code) { case kLAErrorTouchIDNotAvailable: [labelNotSupportTouchID setHidden:NO]; [switchBtn setHidden:YES]; [labelEnableTouchid setHidden:YES]; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self showAlertMessage:@"EyeCheck Pro" message:@"Device does not support Touch ID Service."]; }); break; } } } 

这是一个有点乏味的方法来弄清楚设备是否有物理触摸id传感器。

 + (BOOL)isTouchIDExist { if(![LAContext class]) //Since this mandotory class is not there, that means there is no physical touch id. return false; //Get the current device model name size_t size; sysctlbyname("hw.machine", NULL, &size, NULL, 0); char *model = malloc(size); sysctlbyname("hw.machine", model, &size, NULL, 0); NSString *deviceModel = [NSString stringWithCString:model encoding:NSUTF8StringEncoding]; //Devices that does not support touch id NSArray *deviceModelsWithoutTouchID = [[NSArray alloc] initWithObjects: @"iPhone1,1", //iPhone @"iPhone1,2", //iPhone 3G @"iPhone2,1", //iPhone 3GS @"iPhone3,1", //iPhone 4 @"iPhone3,2", @"iPhone3,3", @"iPhone4,1", //iPhone 4S @"iPhone5,1", //iPhone 5 @"iPhone5,2", @"iPhone5,3", //iPhone 5C @"iPhone5,4", @"iPod1,1", //iPod @"iPod2,1", @"iPod3,1", @"iPod4,1", @"iPod5,1", @"iPod7,1", @"iPad1,1", //iPad @"iPad2,1", //iPad 2 @"iPad2,2", @"iPad2,3", @"iPad2,4",// iPad mini 1G @"iPad2,5", @"iPad2,5", @"iPad2,7", @"iPad3,1", //iPad 3 @"iPad3,2", @"iPad3,3", @"iPad3,4", //iPad 4 @"iPad3,5", @"iPad3,6", @"iPad4,1", //iPad Air @"iPad4,2", @"iPad4,3", @"iPad4,4", //iPad mini 2 @"iPad4,5", @"iPad4,6", @"iPad4,7", nil]; return ![deviceModelsWithoutTouchID containsObject:deviceModel]; 

}

参考: https : //www.theiphonewiki.com/wiki/Models https://en.wikipedia.org/wiki/IOS

对于iOS 11+,您可以使用biometryType: LABiometryType of LAContext 。 更多来自Apple文档:

 /// Indicates the type of the biometry supported by the device. /// /// @discussion This property is set only when canEvaluatePolicy succeeds for a biometric policy. /// The default value is LABiometryTypeNone. @available(iOS 11.0, *) open var biometryType: LABiometryType { get } @available(iOS 11.0, *) public enum LABiometryType : Int { /// The device does not support biometry. @available(iOS 11.2, *) case none /// The device does not support biometry. @available(iOS, introduced: 11.0, deprecated: 11.2, renamed: "LABiometryType.none") public static var LABiometryNone: LABiometryType { get } /// The device supports Touch ID. case touchID /// The device supports Face ID. case faceID }