- 功能需求
用户首次登录APP后,开启指纹验证功能,当APP由后台进入前台或重启时,APP需要验证指纹,通过后才能正常使用APP,无需后端处理。
- 使用场景
- 用户首次登录-》开启指纹验证-》APP进入后台-》APP再次进入前台-》验证用户指纹-》验证成功后,正常使用APP
- 用户首次登录-》开启指纹验证-》双击上滑删除处于后台的APP-》再次打开APP-》验证用户指纹-》验证成功后,正常使用APP
- 涉及的知识点
#import <LocalAuthentication/LocalAuthentication.h>
LocalAuthentication 是苹果封装提供的实现生物信息(Face ID、Touch ID、 device passcode)识别的框架,无法获取用户的生物信息,只能使用已经录入到本机的用户的生物信息。
// 检测设备是否支持生物信息识别
- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * __autoreleasing *)error __attribute__((swift_error(none)))
API_AVAILABLE(macos(10.10), ios(8.0), watchos(3.0), tvos(10.0));
// 验证生物信息
- (void)evaluatePolicy:(LAPolicy)policy
localizedReason:(NSString *)localizedReason
reply:(void(^)(BOOL success, NSError * __nullable error))reply
API_AVAILABLE(macos(10.10), ios(8.0), watchos(3.0), tvos(10.0));
// LAPolicy
LAPolicyDeviceOwnerAuthenticationWithBiometrics // Face ID or Touch ID
LAPolicyDeviceOwnerAuthentication // device passcode
// 查看指纹数据,NSData类型,不透明不可见
context.evaluatedPolicyDomainState
// app进入后台执行的代理方法
- (void)applicationDidEnterBackground:(UIApplication *)application
// app进入前台执行的代理方法
- (void)applicationWillEnterForeground:(UIApplication *)application
// app重启时执行的代理方法
- (void)applicationDidBecomeActive:(UIApplication *)application
- 代码实现-关键代码
// startAutoLoginState用于保存用户设置结果
// MARK: 登录后指纹开启提示
- (void) canEvaluatePolicyTip {
// 初始化上下文对象
LAContext *context = [[LAContext alloc] init];
NSError *error = nil;
// 判断设备是否支持指纹识别功能
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error])
{
// 支持指纹验证
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"登录成功!" message:@"是否启用指纹登录" preferredStyle:UIAlertControllerStyleAlert];
WeakSelf(self)
UIAlertAction *donotStartUseAction = [UIAlertAction actionWithTitle:@"暂不开启" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
[weakSelf.navigationController popViewControllerAnimated:YES];
}];
UIAlertAction *startUseAction = [UIAlertAction actionWithTitle:@"立即开启" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"startAutoLoginState"];
[weakSelf evaluatePolicyAuthentication];
[weakSelf dismissViewControllerAnimated:YES completion:nil];
}];
[alertController addAction:donotStartUseAction];
[alertController addAction:startUseAction];
[self presentViewController:alertController animated:YES completion:nil];
return;
}
else {
// 不支持指纹验证
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
// MARK: 设置页面中设置指纹开启关闭状态
- (IBAction)fingerSwitchClick:(UISwitch *)sender {
// 初始化上下文对象
LAContext *context = [[LAContext alloc] init];
NSError *error = nil;
// 判断设备是否支持指纹识别功能
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error])
{
// 支持指纹验证
if (sender.on) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"startAutoLoginState"];
[SVProgressHUD showSuccessWithStatus:@"开启成功"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
} else {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
}
return;
}
else {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
[SVProgressHUD showErrorWithStatus:@"设备不支持指纹或锁屏密码"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}
}
// MARK: 指纹登录验证
- (void) evaluatePolicyAuthentication {
WeakSelf(self)
LAContext *context = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = @"请按住Home键完成验证";
// 判断设备是否支持指纹识别
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&authError])
{
[context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:myLocalizedReasonString reply:^(BOOL success, NSError * _Nullable error) {
if(success)
{
NSLog(@"%@",context.evaluatedPolicyDomainState);
NSLog(@"指纹认证成功");
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 处理验证成功后逻辑
}];
}
else
{
switch (error.code)
{
case LAErrorAuthenticationFailed:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"验证失败"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
}
break;
case LAErrorSystemCancel:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"系统取消输入验证信息"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
}
break;
case LAErrorPasscodeNotSet:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"设备系统未设置密码"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
}
break;
case LAErrorUserCancel:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"用户取消输入验证信息"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
}
break;
case LAErrorUserFallback:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"验证被取消"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
}
break;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0
case LAErrorBiometryLockout:
{
[SVProgressHUD showErrorWithStatus:@"Touch ID被锁,需要用户输入密码解锁"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}
break;
case LAErrorAppCancel:
{
NSLog(@"用户不能控制情况下APP被挂起"); // -9
}
break;
case LAErrorInvalidContext:
{
NSLog(@"LAContext传递给这个调用之前已经失效"); // -10
}
break;
#else
#endif
default:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"其他情况,切换主线程处理");
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
}];
break;
}
}
}
}];
}
else
{
NSLog(@"设备不支持验证信息");
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
switch (authError.code)
{
case LAErrorBiometryNotEnrolled:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"设备系统未设置指纹"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
break;
}
case LAErrorPasscodeNotSet:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"设备系统未设置密码"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
break;
}
default:
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[SVProgressHUD showErrorWithStatus:@"验证信息不可用"];
[SVProgressHUD setFadeInAnimationDuration:0];
[SVProgressHUD dismissWithDelay:2];
}];
break;
}
}
}
}
网友评论