苹果在 iOS 8 中向开发者开放了 Touch ID 的 API,本文主要介绍它的使用。
从哪里入手
其实关于 Touch ID 的 API 全部都在一个叫做 LocalAuthentication
的 framework 中,其中仅含有三个头文件:
-
LAContext.h
-
LAError.h
-
LAPublicDefines.h
而且事实上,实际使用中你可能仅仅用到 LAContext
中的 两个方法:
// 设备是否支持 Touch ID
- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * __autoreleasing *)error;
这个方法十分简单,用于检查设备是否支持 Touch ID,并返回布尔值。唯一值得说明的是 LAPolicy
,目前它只有 LAPolicyDeviceOwnerAuthenticationWithBiometrics
这一个值可用。
// 使用 Touch ID 验证身份
- (void)evaluatePolicy:(LAPolicy)policy localizedReason:(NSString *)localizedReason reply:(void(^)(BOOL success, NSError *error))reply;
这个方法也没有什么难度:
-
第一个参数
Policy
和上一个方法相同; -
第二个参数
localizedReason
是在指纹图标下的一句描述信息,通常用来指示用户验证指纹的原因(图中的1
部分); -
第三个参数
reply
是一个 block,当指纹验证成功,或被用户取消(LAErrorUserCancel
),或被系统中断(LAErrorSystemCancel
),或用户选择输入密码(LAErrorUserFallback
),则会执行此 block 中的代码,该 block 的第一个参数success
为布尔值,表示指纹验证是否成功,第二个参数表示错误信息。
有了这两个方法,我们即可实现在支持 Touch ID 的设备上进行指纹校验,接下来我们来做进一步的实现与封装。
使用与封装
首先,尽管很简单,但为了方便以后重复使用,我们新建 MXTouchID
类来做管理封装。
导入相关框架:
@import LocalAuthentication;
然后,在 MXTouchID.m
文件中封装一个用于校验 Touch ID 是否可用的方法,由于我们不需要实例化,因此此方法为类方法:
#pragma mark - 判断指纹是否可用
+ (BOOL)touchIDEnabled {
LAContext *context = [[LAContext alloc] init];
NSError *error;
BOOL success = [context canEvaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
if (success) {
return YES;
} else {
NSLog(@"%@", error);
return NO;
}
}
接下来,如果 Touch ID 可用,我们还要做进一步的验证操作,同理,封装到另一个类方法中:
#pragma mark - 验证指纹
+ (void)touchIDEvaluateWithMessage:(NSString *)message localizedFallbackTitle:(NSString *)localizedFallbackTitle completed:(void (^)(BOOL success, NSError *authenticationError))completion {
LAContext *context = [[LAContext alloc] init];
context.localizedFallbackTitle = localizedFallbackTitle;
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:NSLocalizedString(message, nil) reply:
^(BOOL success, NSError *authenticationError) {
if (completion) {
completion(success, authenticationError);
}
}];
}
之所以为这个封装方法添加参数 message
和 localizedFallbackTitle
,是因为这两个部分是允许自定义的,他们分别对应前面图中的 1
和 2
部分。如果你不需要输入密码(图中的 2
部分)操作,你可以将 localizedFallbackTitle
的值设置为 @""
(或者干脆对其进行设置)来隐藏输入密码的按钮(图中的 2
部分)。
在这个方法中还有一个 block 参数名为 completion
,无论是否验证成功,他都将被调用(如果它的值不为 nil
),在 completion
内部又有参数 BOOL success
和 NSError *authenticationError
,在指纹验证的反馈 block 中将对应的值传入以便使用。如果你需要根据验证失败的不同情况做出反应,你可以通过判断 NSError *authenticationError
的 code
属性值与三种错误情况——用户取消(LAErrorUserCancel
)、系统中断(LAErrorSystemCancel
)、用户选择输入密码(LAErrorUserFallback
)——是否匹配来实现。
最后,不要忘了在头文件中对这些方法进行声明。