在許多 App 的應用上,常常會使用到使用者登入的功能,尤其是金融交易的 App,用 FaceID 或 TouchID 更是一種不得不用上的趨勢,畢竟任何一個用戶都不希望自己在登入時還要再輸入一次密碼。而 TouchID 是一個第三方封裝好的 FaceID、TouchID 驗證工具,使用起來相當容易,程式碼也相當簡潔不囉嗦,個人是蠻推薦使用的喔!
而在 TDTouch 的「.h」中,其實就有訂了以下的函式可以使用。
@interface TDTouchID : LAContext
typedef void (^StateBlock)(TDTouchIDState state,NSError *error);
+ (instancetype)sharedInstance;
/**
启动生物验证
@param desc Touch显示的描述
@param block 回调状态的block
*/
- (void)td_showTouchIDWithDescribe:(NSString *)desc BlockState:(StateBlock)block;
/**
启动生物验证
@param desc Touch显示的描述
@param faceDesc FaceID状态下显示的描述
@param block 回调状态的block
*/
- (void)td_showTouchIDWithDescribe:(NSString *)desc FaceIDDescribe:(NSString *)faceDesc BlockState:(StateBlock)block;
// 判断设备支持哪种认证方式 TouchID & FaceID
- (TDTouchIDSupperType)td_canSupperBiometrics;
@end
也因此,我們如果要判斷 iOS 裝置是否有支援手機辨識,以官方的範例來說,我們只需要做以下的事情就好。
//判断是否支持生物验证(此处根据不同类型来显示不同的图标)
TDTouchIDSupperType type = [[TDTouchID sharedInstance] td_canSupperBiometrics];
switch (type) {
case TDTouchIDSupperTypeFaceID:
NSLog(@"????支持FaceID");
break;
case TDTouchIDSupperTypeTouchID:
NSLog(@"????支持TouchID");
break;
case TDTouchIDSupperTypeNone:
NSLog(@"????不支持生物验证");
break;
default:
break;
}
在得知手機支援 Touch ID 或 Face ID 後,接下來就是驗證了,怎樣呼叫呢?其實也只要用以下的方式來呼叫就好了。
/**
验证 TouchID
*/
- (void)touchVerification {
[[TDTouchID sharedInstance] td_showTouchIDWithDescribe:@"通过Home键验证已有指纹" FaceIDDescribe:@"通过已有面容ID验证" BlockState:^(TDTouchIDState state, NSError *error) {
if (state == TDTouchIDStateNotSupport) { //不支持TouchID/FaceID
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"当前设备不支持生物验证" message:@"请输入密码来验证" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
alertview.alertViewStyle = UIAlertViewStyleSecureTextInput;
[alertview show];
} else if (state == TDTouchIDStateSuccess) { //TouchID/FaceID验证成功
NSLog(@"jump");
TDHomeViewController *homeVc = [[TDHomeViewController alloc] init];
[self.navigationController pushViewController:homeVc animated:YES];
} else if (state == TDTouchIDStateInputPassword) { //用户选择手动输入密码
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:nil message:@"请输入密码" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
alertview.alertViewStyle = UIAlertViewStyleSecureTextInput;
[alertview show];
}
// ps:以上的状态处理并没有写完全!
// 在使用中你需要根据回调的状态进行处理,需要处理什么就处理什么
}];
}
以金融交易的 App 來說,通常在「applicationWillResignActive」中都會訂立一個遮蔽的畫面,主要的目的是讓你的 App 縮到背景或在不同程式間切換時,使用者不會看到 App 正在執行的畫面,但使用「Touch ID」或「Face ID」會呼叫「applicationWillResignActive」,如果我們要在登入頁使用「Touch ID」或「Face ID」,但使用者看到的卻不是登入頁,而是遮蔽頁,那不是很怪的一件事嗎?所以,我們必須在 TDTouchID 動一點手腳。這時我們可以宣告一個變數 m_isUsingTouchID,來判斷是否正在使用 Touch ID 或是 Face ID。
@interface TDTouchID()
@property (assign, nonatomic) BOOL m_isUsingTouchID;
@end
接下來,改寫這隻程式的 sharedInstance。
+ (instancetype)sharedInstance {
static TDTouchID *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[TDTouchID alloc] init];
instance.m_isUsingTouchID = NO;
});
return instance;
}
新增一個函式來回傳是否正在使用「臉部辨識/指紋辨識」
/**
是否正在使用「指紋辨識/臉部辨識」
*/
+ (BOOL) isUsingTouchID
{
TDTouchID* touchID = [self sharedInstance];
return touchID.m_isUsingTouchID;
}
最後,找到「LAPolicyDeviceOwnerAuthenticationWithBiometrics」,並在這行程式之前加入「self.m_isUsingTouchID」,而在 reply 的 Block 記得寫「self->_m_isUsingTouchID = NO;」
self.m_isUsingTouchID = YES;
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:descStr reply:^(BOOL success, NSError * _Nullable error) {
self->_m_isUsingTouchID = NO;
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"TouchID 验证成功");
block(TDTouchIDStateSuccess,error);
});
}
};
最後,別忘了在 Appdelegate 的 applicationWillResignActive 加上以下的程式碼:
- (void)applicationWillResignActive:(UIApplication *)application
{
if ([TDTouchID isUsingTouchID]){
return;
}
if (self.m_TopmaskView == nil) {
self.m_TopmaskView = [[[NSBundle mainBundle] loadNibNamed: NSStringFromClass([MaskView class])
owner:self options:nil] objectAtIndex:0];
self.m_TopmaskView.frame = self.window.frame;
[self.window addSubview:self.m_TopmaskView];//加上遮蔽畫面
}
}
Appdelegate 的 applicationDidEnterBackground 也別忘了喔
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if ([TDTouchID isUsingTouchID]){
return;
}
if (self.m_TopmaskView == nil) {
self.m_TopmaskView = [[[NSBundle mainBundle] loadNibNamed: NSStringFromClass([MaskView class])
owner:self options:nil] objectAtIndex:0];
self.m_TopmaskView.frame = self.window.frame;
[self.window addSubview:self.m_TopmaskView];//加上遮蔽畫面
}
}
而以上的程式碼供參考,若有問題再請提出啦!