iOS --- Touch ID指紋解鎖

最近在項目中剛好用到了TouchId指紋解鎖功能大咱,之前也沒有接觸過,立馬百度看看究竟是要如何使用轻专,發(fā)現(xiàn)其實也不是很復雜。
文章后面有封裝的工具方法察蹲,可以直接copy使用请垛。

下面開始跟大家分享一下:

一、使用要點:

(1)需要導入庫 LocalAuthentication.framework
(2)引入頭文件 #import <LocalAuthentication/LocalAuthentication.h>
(3)指紋解鎖只支持iOS 8及以上的版本
(4)如果指紋驗證多次錯誤會被鎖定洽议,只能通過輸入手機密碼來重新啟用宗收。iOS 9 提供了一個方法,可以直接調起密碼輸入界面亚兄。
(5)所有操作必須要回到主線程混稽,因為系統(tǒng)的驗證是在子線程。
(6)所有的錯誤處理是通過一個枚舉來判斷處理的审胚,具體作用看注釋

二匈勋、代碼要點

(1)這是判斷系統(tǒng)版本是否大于iOS 8

if (!(MQ_CURRENT_DEVICE_SYSTEM_VERSION >= 8.0)) {
        result(NO, MQ_TOUCHID_ERROR_SYSTEM_NOT_SUPPORT);
        return;
    }

(2)判斷是否可用

// 返回bool值
[authenContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]

(3)下面的就是重要的點 :

指紋解鎖多次失敗以后,系統(tǒng)會鎖定TouchID硬件必須通過輸入手機密碼來解鎖膳叨,如果系統(tǒng)是iOS8的話洽洁,TouchID被鎖定以后只能通過重啟手機來重新開啟。

//系統(tǒng)提供的兩個驗證的枚舉
typedef NS_ENUM(NSInteger, LAPolicy)
{
    LAPolicyDeviceOwnerAuthenticationWithBiometrics NS_ENUM_AVAILABLE(NA, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0) = kLAPolicyDeviceOwnerAuthenticationWithBiometrics,

    LAPolicyDeviceOwnerAuthentication NS_ENUM_AVAILABLE(10_11, 9_0) = kLAPolicyDeviceOwnerAuthentication

} NS_ENUM_AVAILABLE(10_10, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0);

kLAPolicyDeviceOwnerAuthentication 這個值只有在iOS9.0及以后才可以使用菲嘴,利用這個值可以調出輸入密碼來解鎖TouchID的界面饿自。

 [authenContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                  localizedReason:TOUCHID_NOTICE_MESSAGE
                            reply:^(BOOL success, NSError * _Nullable error) {
                                if (success) {
                                  //已經重新解鎖Touchid
                                } 
                            }];

開始指紋解鎖代碼

[authenContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                  localizedReason:TOUCHID_NOTICE_MESSAGE
                            reply:^(BOOL success, NSError * _Nullable error) {
                                if (success) {
                                   // 解鎖成功
                                } 
                            }];

(4)看看系統(tǒng)的錯誤枚舉

typedef NS_ENUM(NSInteger, LAError)
{
    /// Authentication was not successful, because user failed to provide valid credentials.
    LAErrorAuthenticationFailed = kLAErrorAuthenticationFailed,
    
    /// Authentication was canceled by user (e.g. tapped Cancel button).
    LAErrorUserCancel = kLAErrorUserCancel,
    
    /// Authentication was canceled, because the user tapped the fallback button (Enter Password).
    LAErrorUserFallback = kLAErrorUserFallback,
    
    /// Authentication was canceled by system (e.g. another application went to foreground).
    LAErrorSystemCancel = kLAErrorSystemCancel,
    
    /// Authentication could not start, because passcode is not set on the device.
    LAErrorPasscodeNotSet = kLAErrorPasscodeNotSet,

    /// Authentication could not start, because Touch ID is not available on the device.
    LAErrorTouchIDNotAvailable NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotAvailable") = kLAErrorTouchIDNotAvailable,

    /// Authentication could not start, because Touch ID has no enrolled fingers.
    LAErrorTouchIDNotEnrolled NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotEnrolled") = kLAErrorTouchIDNotEnrolled,

    /// Authentication was not successful, because there were too many failed Touch ID attempts and
    /// Touch ID is now locked. Passcode is required to unlock Touch ID, e.g. evaluating
    /// LAPolicyDeviceOwnerAuthenticationWithBiometrics will ask for passcode as a prerequisite.
    LAErrorTouchIDLockout NS_ENUM_DEPRECATED(10_11, 10_13, 9_0, 11_0, "use LAErrorBiometryLockout")
        __WATCHOS_DEPRECATED(3.0, 4.0, "use LAErrorBiometryLockout") __TVOS_DEPRECATED(10.0, 11.0, "use LAErrorBiometryLockout") = kLAErrorTouchIDLockout,

    /// Authentication was canceled by application (e.g. invalidate was called while
    /// authentication was in progress).
    LAErrorAppCancel NS_ENUM_AVAILABLE(10_11, 9_0) = kLAErrorAppCancel,

    /// LAContext passed to this call has been previously invalidated.
    LAErrorInvalidContext NS_ENUM_AVAILABLE(10_11, 9_0) = kLAErrorInvalidContext,

    /// Authentication could not start, because biometry is not available on the device.
    LAErrorBiometryNotAvailable NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotAvailable,

    /// Authentication could not start, because biometry has no enrolled identities.
    LAErrorBiometryNotEnrolled NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotEnrolled,

    /// Authentication was not successful, because there were too many failed biometry attempts and
    /// biometry is now locked. Passcode is required to unlock biometry, e.g. evaluating
    /// LAPolicyDeviceOwnerAuthenticationWithBiometrics will ask for passcode as a prerequisite.
    LAErrorBiometryLockout NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryLockout,
    
    /// Authentication failed, because it would require showing UI which has been forbidden
    /// by using interactionNotAllowed property.
    LAErrorNotInteractive API_AVAILABLE(macos(10.10), ios(8.0), watchos(3.0), tvos(10.0)) = kLAErrorNotInteractive,
} NS_ENUM_AVAILABLE(10_10, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0);

三、這是我封裝的工具類

(1)MQTouchID.h文件

//
//  MQTouchID.h
//  Test
//
//  Created by PasserMontanus on 2018/3/21.
//  Copyright ? 2018年 lgl. All rights reserved.
//
#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, MQ_TOUCHID_ERROR) {
    // 系統(tǒng)不支持 要大于 8.0
    MQ_TOUCHID_ERROR_SYSTEM_NOT_SUPPORT = 0,
    // 驗證成功
    MQ_TOUCHID_ERROR_SUCCESS = 1,
    // 系統(tǒng)取消授權龄坪,如其他APP切入
    MQ_TOUCHID_ERROR_SYSTEM_CANCEL = -4,
    // 用戶取消驗證Touch ID
    MQ_TOUCHID_ERROR_USER_CANCEL = -2,
    // 用戶選擇輸入密碼
    MQ_TOUCHID_ERROR_USER_FALLBACK = -3,
    //授權失敗
    MQ_TOUCHID_ERROR_FAILED = -1,
    //系統(tǒng)未設置密碼 這個密碼在用戶指紋多次驗證失敗的時候要用他來重新激活
    MQ_TOUCHID_ERROR_PASSCODE_NOT_SET = -5,
    //設備Touch ID不可用昭雌,例如未打開
    MQ_TOUCHID_ERROR_NOT_AVAILABLE = -6,
    //設備Touch ID不可用,用戶沒有錄入指紋
    MQ_TOUCHID_ERROR_NOT_ENROLLED = -7,
    //身份驗證失敗健田,因為它需要顯示已被禁止的UI
    MQ_TOUCHID_ERROR_NOT_INTERACTIVE = -1004,
    // 設備Touch ID被鎖定烛卧,輸入錯誤的次數(shù)過多 這個時候需要密碼來重新激活
    MQ_TOUCHID_ERROR_LOCKOUT = -8 ,
    //應用程序已取消身份驗證
    MQ_TOUCHID_ERROR_APP_CANCEL = -9,
    // 傳遞給此調用的LAContext先前已失效。
    MQ_TOUCHID_ERROR_INVALID_CONTEXT = -10
};

typedef void(^MQTouchIDResult)(BOOL isSuccess, MQ_TOUCHID_ERROR error_code);

@interface MQTouchID : NSObject

/**
 開始驗證 TouchID 指紋解鎖 (需要導入 LocalAuthentication.framework)
 
 注意: 結果回調以后的操作都需要回到主線程 這個驗證是在子線程里面執(zhí)行的
 */
+ (void)validateTouchID:(MQTouchIDResult)result;

@end

(2)MQTouchID.m文件

//
//  MQTouchID.m
//  Test
//
//  Created by PasserMontanus on 2018/3/21.
//  Copyright ? 2018年 lgl. All rights reserved.
//
#import "MQTouchID.h"
#import <LocalAuthentication/LocalAuthentication.h>

#define MQ_CURRENT_DEVICE_SYSTEM_VERSION ([[UIDevice currentDevice]systemVersion].doubleValue)

static NSString  * TOUCHID_NOTICE_MESSAGE          = @"通過Home鍵驗證已有的手機指紋";
static NSString  * TOUCHID_NOTICE_RESTART_MESSAGE  = @"重新開啟TouchID功能";


@implementation MQTouchID


+ (void)validateTouchID:(MQTouchIDResult)result {
    if (!(MQ_CURRENT_DEVICE_SYSTEM_VERSION >= 8.0)) {
        result(NO, MQ_TOUCHID_ERROR_SYSTEM_NOT_SUPPORT);
        return;
    }
    LAContext *authenContext = [[LAContext alloc]init];
    NSError* error = nil;
    if ([authenContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) { // 可用
        [self startValidateTouchID:authenContext result:result];
    } else { // 不可用
        MQ_TOUCHID_ERROR erroCode =  [self errorCode:error.code];
        [self processingTouchIdError:authenContext erroCode:erroCode result:result];
    }
}


+ (void)startValidateTouchID:(LAContext *)authenContext result:(MQTouchIDResult)result {
    [authenContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                  localizedReason:TOUCHID_NOTICE_MESSAGE
                            reply:^(BOOL success, NSError * _Nullable error) {
                                if (success) {
                                    result(YES,MQ_TOUCHID_ERROR_SUCCESS);
                                } else {
                                    MQ_TOUCHID_ERROR erroCode =  [self errorCode:error.code];
                                    [self processingTouchIdError:authenContext erroCode:erroCode result:result];
                                }
                            }];
}

+ (void)processingTouchIdError:(LAContext *)authenContext
                      erroCode:(MQ_TOUCHID_ERROR)erroCode
                        result:(MQTouchIDResult)result {
    
    if (@available(iOS 9.0, *)) {
        if (erroCode == MQ_TOUCHID_ERROR_LOCKOUT) {
            [authenContext evaluatePolicy:LAPolicyDeviceOwnerAuthentication
                          localizedReason:TOUCHID_NOTICE_RESTART_MESSAGE
                                    reply:^(BOOL success, NSError * _Nullable error) {
                                        if (success) {
                                            [self validateTouchID:result];
                                        } else {
                                            result(NO, MQ_TOUCHID_ERROR_USER_CANCEL);
                                        }
                                    }];
        
        } else {
            result(NO, erroCode);
        }
    } else {
        result(NO, erroCode);
    }
}

+ (MQ_TOUCHID_ERROR)errorCode:(NSInteger )errorCode {
    switch (errorCode) {
        case LAErrorSystemCancel:{ // 系統(tǒng)取消授權妓局,如其他APP切入
            return MQ_TOUCHID_ERROR_SYSTEM_CANCEL;
            break;
        }
        case LAErrorUserCancel:{ // 用戶取消驗證Touch ID
            return MQ_TOUCHID_ERROR_USER_CANCEL;
            break;
        }
        case LAErrorUserFallback:{ // 用戶選擇輸入密碼
            return MQ_TOUCHID_ERROR_USER_FALLBACK;
            break;
        }
        case LAErrorAuthenticationFailed:{ // //授權失敗
            return MQ_TOUCHID_ERROR_FAILED;
            break;
        }
        case LAErrorPasscodeNotSet: { //系統(tǒng)未設置密碼 這個密碼在用戶指紋多次驗證失敗的時候要用他來重新激活
            return MQ_TOUCHID_ERROR_PASSCODE_NOT_SET;
            break;
        }
        case LAErrorTouchIDNotAvailable: { //設備Touch ID不可用唱星,例如未打開
            return MQ_TOUCHID_ERROR_NOT_AVAILABLE;
            break;
        }
        case LAErrorTouchIDNotEnrolled: { //設備Touch ID不可用雳旅,用戶沒有錄入指紋
            return MQ_TOUCHID_ERROR_NOT_ENROLLED;
            break;
        }
        case LAErrorNotInteractive: { //   身份驗證失敗,因為它需要顯示已被禁止的UI
            return MQ_TOUCHID_ERROR_NOT_INTERACTIVE;
            break;
        }
        default:{
            if (@available(iOS 9.0, *)) {
                if (errorCode == LAErrorTouchIDLockout) { // 設備Touch ID被鎖定间聊,輸入錯誤的次數(shù)過多 這個時候需要密碼來重新激活
                    return MQ_TOUCHID_ERROR_LOCKOUT;
                    break;
                } else {
                    if (errorCode == LAErrorInvalidContext) {
                        return MQ_TOUCHID_ERROR_INVALID_CONTEXT;
                        break;
                    } else if (errorCode == LAErrorAppCancel) {
                        return MQ_TOUCHID_ERROR_APP_CANCEL;
                        break;
                    } else {
                        return MQ_TOUCHID_ERROR_FAILED;
                        break;
                    }
                }
            } else {
                return MQ_TOUCHID_ERROR_FAILED;
                break;
            }
        }
    }
}

@end

四攒盈、最后結語

(1)最后的結果回調以后的操作一定要在主線程,系統(tǒng)驗證在子線程進行
(2)以上就是我的一點小總結哎榴,歡迎大家指正型豁。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尚蝌,隨后出現(xiàn)的幾起案子迎变,更是在濱河造成了極大的恐慌,老刑警劉巖飘言,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衣形,死亡現(xiàn)場離奇詭異,居然都是意外死亡姿鸿,警方通過查閱死者的電腦和手機谆吴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苛预,“玉大人句狼,你說我怎么就攤上這事∪饶常” “怎么了腻菇?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長昔馋。 經常有香客問我筹吐,道長,這世上最難降的妖魔是什么秘遏? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任丘薛,我火速辦了婚禮,結果婚禮上垄提,老公的妹妹穿的比我還像新娘榔袋。我一直安慰自己周拐,他們只是感情好铡俐,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妥粟,像睡著了一般审丘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勾给,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天滩报,我揣著相機與錄音锅知,去河邊找鬼。 笑死脓钾,一個胖子當著我的面吹牛售睹,可吹牛的內容都是我干的。 我是一名探鬼主播可训,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼昌妹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了握截?” 一聲冷哼從身側響起飞崖,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谨胞,沒想到半個月后固歪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡胯努,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年牢裳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片康聂。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡贰健,死狀恐怖,靈堂內的尸體忽然破棺而出恬汁,到底是詐尸還是另有隱情伶椿,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布氓侧,位于F島的核電站脊另,受9級特大地震影響,放射性物質發(fā)生泄漏约巷。R本人自食惡果不足惜偎痛,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望独郎。 院中可真熱鬧踩麦,春花似錦、人聲如沸氓癌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贪婉。三九已至反粥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背才顿。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工莫湘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人郑气。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓幅垮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尾组。 傳聞我的和親對象是個殘疾皇子军洼,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內容

  • 用到的組件 1、通過CocoaPods安裝 2演怎、第三方類庫安裝 3匕争、第三方服務 友盟社會化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 14,618評論 1 180
  • 在開始代碼之前,先認識一下LAPolicy爷耀。 LAPolicy是一個枚舉甘桑,有兩個值 第一個枚舉值,用戶驗證失敗3次...
    夜涼聽風雨閱讀 6,382評論 0 16
  • 一直想玩玩指紋解鎖歹叮,近期時間比較閑跑杭,就研究了一下這個指紋解鎖。這個功能實現(xiàn)起來還是很簡單的咆耿,雖然看起來比較高大上德谅,...
    weicyNO_1閱讀 3,204評論 0 3
  • 凌晨一點窄做、敢小姐放下手中的kindle、拿起已經黑屏的手機慰技。點擊微信椭盏、開始著睡前最后一次刷朋友圈。突然跳出一個好友...
    敢姑娘閱讀 1,475評論 29 7
  • 是的吻商,我成為不了一個詩人了 當我的右手做過愛以后 連紙筆都抓握不住 詩句都書寫不成行掏颊,包括字詞 是的,我成為不了一...
    景大別閱讀 245評論 0 0