上一篇文章簡單的寫了對于touchid的簡單了解。因為太懶了,就沒有寫實例,現在就單獨寫一篇應用吧,這篇想做的就是一個模仿那個叫啥軟件來著,某某理財類類的軟件的一個指紋驗證解鎖。我們做出來的頁面應該如下圖,在app掛起到后臺的時候再點擊到前臺的時候回出現如下頁面:
app喚醒的時候出現的畫面
點擊取消按鈕出現的頁面
這里我先掛上github的鏈接地址,畢竟本文的篇幅較長,也沒什么人有耐心有時間看到最后,頂多看下demo,快速的知道怎么調用啥的就可以了。(popviewfortouchid)
因為我之前沒遇到個這種情況,所以我做的都是自己瞎搞搞出來的,也不知道平時大家做的時候是怎么做的,就搞出來這樣的,這里我打算用兩種方法來實現,不過這個東西放進app中貌似是需要適配的。還是有些許問題的??赡芤{下。
在app被喚醒的時候,出現頁面我用了兩種方式,一種是present出來一個單獨的頁面,一種方式是自定義彈出view。
但是本文呢,主要就介紹一下彈出式view的方式,因為present的方式跟這種方式差別就是在于一個是view一個是controller,主要的思想還是一樣的。
第一部分
第一步
引入需要用的文件,以及創建pch文件,因為是小demo,所以一些宏定義直接丟進去就可以了。
第二步
創建pch文件,引入一些需要用到的文件以及宏定義,這里要是有問題的話可以參照我之前一篇文章寫的引入pch文件,當然也可以老老實實的每個文件里都去引入頭文件啥的,這個很隨意的,畢竟是demo。
1
2
3
4
5
6
7
8
9
10
11
|
#import "appdelegate.h" #import "wjtouchid.h" #import "mbprogresshud.h" #import "mbprogresshud+add.h" // 屏幕bounds #define ylsscreenbounds [uiscreen mainscreen].bounds //位置 #define zlrect(x, y, w, h) cgrectmake([uiscreen mainscreen].bounds.size.width * x, [uiscreen mainscreen].bounds.size.height * y, [uiscreen mainscreen].bounds.size.width * w, [uiscreen mainscreen].bounds.size.height * h) //字體大小 #define zcfont(f) [uiscreen mainscreen].bounds.size.width * f |
第三步
實現基礎頁面,如下圖
聲明變量,遵守指紋驗證控件的協議
1
2
3
4
5
6
7
|
@interface viewcontroller ()<wjtouchiddelegate> /** noticelabel */ @property (nonatomic,strong) uilabel *label; /** uiswitch */ @property (nonatomic,strong) uiswitch *touchidswitch; @property (nonatomic, strong) wjtouchid *touchid; @end |
懶加載
1
2
3
4
5
6
7
8
|
-(uiswitch *)touchidswitch { if (!_touchidswitch) { self.touchidswitch = [[uiswitch alloc]init]; } return _touchidswitch; } |
添加子控件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
-( void )setsubviews { self.label = [[uilabel alloc]init]; [self.view addsubview:self.label]; [self.label setframe:zlrect(0, 100/667, 1, 20/667)]; [self.label settext:@ "指紋解鎖" ]; [self.label settextalignment:nstextalignmentcenter]; [self.label setfont:[uifont systemfontofsize:zcfont(18/375)]]; self.touchidswitch = [[uiswitch alloc]init]; [self.touchidswitch setframe:zlrect(160/375, 200/667, 50/375, 28/667)]; [self.view addsubview:self.touchidswitch]; if ([[[nsuserdefaults standarduserdefaults]objectforkey:@ "touchid" ] isequaltostring:@ "1" ]) { self.touchidswitch.on = yes; } else { self.touchidswitch.on = no; } [self.touchidswitch addtarget:self action:@selector(changeswitch:) forcontrolevents:uicontroleventvaluechanged]; } |
這里要說一下
[[[nsuserdefaults standarduserdefaults]objectforkey:@"touchid"] isequaltostring:@"1"]
這個我是將是否設置了指紋驗證存到了本地,因為當你進入設置頁面的時候,必須知道你本機是否已經設置了指紋驗證,這里存在著設置與未設置的一個頁面ui差別,我這邊就是用switch的開關來打開關閉指紋驗證,也是用開關狀態來表示指紋驗證是否打開。
第四步
在viewdidload方法中調用設置子控件的方法,并且實現開關切換的方法。
1
2
3
4
|
- ( void )viewdidload { [super viewdidload]; [self setsubviews]; } |
切換方法里呢,就是需要調用者會問驗證,一般軟件設置指紋驗證的時候都會要求你先驗證一下子,我在這里設置成只要你開或關閉都需要驗證一下。
1
2
3
4
5
6
7
8
|
-( void )changeswitch:(id)sender { nslog(@ "------changeswitch-------" ); wjtouchid *touchid = [[wjtouchid alloc]init]; [touchid startwjtouchidwithmessage:wjnotice(@ "自定義信息" , @ "the custom message" ) fallbacktitle:wjnotice(@ "" , @ "fallback title" ) delegate:self]; self.touchid = touchid; } |
第五步
在上述調用指紋驗證成功后,必須得實現它的回調函數,在成功或者失敗的方法中寫上你需要執行的代碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
//touchid驗證成功 - ( void ) wjtouchidauthorizesuccess { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; if (self.touchidswitch.on == yes) { [mbprogresshud showtext:@ "成功開啟指紋解鎖" view:self.view]; [[nsuserdefaults standarduserdefaults] setobject:@ "1" forkey:@ "touchid" ]; } else { [mbprogresshud showtext:@ "指紋解鎖關閉成功" view:self.view]; [[nsuserdefaults standarduserdefaults] setobject:@ "0" forkey:@ "touchid" ]; } } //touchid驗證失敗 - ( void ) wjtouchidauthorizefailure { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; if (self.touchidswitch.on == yes){ self.touchidswitch.on = no; [mbprogresshud showtext:@ "指紋解鎖開啟失敗" view:self.view]; [[nsuserdefaults standarduserdefaults] setobject:@ "0" forkey:@ "touchid" ]; } else { self.touchidswitch.on = yes; [mbprogresshud showtext:@ "指紋解鎖關閉失敗" view:self.view]; [[nsuserdefaults standarduserdefaults] setobject:@ "1" forkey:@ "touchid" ]; } } //取消touchid驗證 (用戶點擊了取消) - ( void ) wjtouchidauthorizeerrorusercancel { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; if (self.touchidswitch.on == yes){ self.touchidswitch.on = no; [[nsuserdefaults standarduserdefaults] setobject:@ "0" forkey:@ "touchid" ]; } else { self.touchidswitch.on = yes; [[nsuserdefaults standarduserdefaults] setobject:@ "1" forkey:@ "touchid" ]; } } //在驗證的touchid的過程中被系統取消 例如突然來電話、按了home鍵、鎖屏 - ( void ) wjtouchidauthorizeerrorsystemcancel { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; if (self.touchidswitch.on == yes){ self.touchidswitch.on = no; [[nsuserdefaults standarduserdefaults] setobject:@ "0" forkey:@ "touchid" ]; } else { self.touchidswitch.on = yes; [[nsuserdefaults standarduserdefaults] setobject:@ "1" forkey:@ "touchid" ]; } } //多次連續使用touch id失敗,touch id被鎖,需要用戶輸入密碼解鎖 - ( void ) wjtouchidauthorizelaerrortouchidlockout { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; [mbprogresshud showtext:@ "驗證失敗" view:self.view]; } //當前軟件被掛起取消了授權(如突然來了電話,應用進入前臺) - ( void ) wjtouchidauthorizelaerrorappcancel { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; if (self.touchidswitch.on == yes){ self.touchidswitch.on = no; [[nsuserdefaults standarduserdefaults] setobject:@ "0" forkey:@ "touchid" ]; } else { self.touchidswitch.on = yes; [[nsuserdefaults standarduserdefaults] setobject:@ "1" forkey:@ "touchid" ]; } } //當前軟件被掛起取消了授權 (授權過程中,lacontext對象被釋) - ( void ) wjtouchidauthorizelaerrorinvalidcontext { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; if (self.touchidswitch.on == yes){ self.touchidswitch.on = no; [[nsuserdefaults standarduserdefaults] setobject:@ "0" forkey:@ "touchid" ]; } else { self.touchidswitch.on = yes; [[nsuserdefaults standarduserdefaults] setobject:@ "1" forkey:@ "touchid" ]; } } |
以上呢,我是沒有判斷是否支持touchid來寫,是直接按照可以支持的來寫的,大家在實際操作工程中還是需要加一下判斷條件,因為現在還是有不支持touchid的機型的。然后就是要說一下下面這個。
[[nsuserdefaults standarduserdefaults]setobject:@"yes" forkey:@"touchidison"];
這個值我也不知道我是用來干嘛的,好像就是告訴我你設置了指紋驗證了,然后在app喚醒的時候要根據一個值來判斷是否需要調用指紋驗證服務,我后來想了想,好像只要
[[[nsuserdefaults standarduserdefaults]objectforkey:@"touchid"] isequaltostring:@"1"]
這個就可以了,但是仔細想想還是再加上一個好分辨一點,畢竟就把一個當做判斷switch是否打開,一個判斷喚醒的時候要不要調用的吧。在不同的回調函數里面需要寫的東西還是有差別的。這樣上面寫完之后,就等于實現一個簡單的基礎頁面,當然這個還不是什么大問題,因為這個很簡單,下面就是要實現彈出view了。篇幅好像有點長了,我自己看的也有點煩了都。。。。。
第二部分
第一步
創建自定義的view。在.h文件中寫入方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@interface ylstouchidview : uiview /** * 快速創建 */ +(instancetype)touchidview; /** * 彈出 */ -( void )show; -( void )showinview:(uiview *)view; @end |
第二步
在.m文件中聲明控件,設置頁面大小,以及遵守協議,在頁面出來的同時就要調用驗證服務。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
@interface ylstouchidview()<wjtouchiddelegate> /** 指紋解鎖的button */ @property (nonatomic,strong) uibutton *touchidbtn; /** 頭像 */ @property (nonatomic,strong) uiimageview *iconview; /** 用戶名 */ @property (nonatomic,strong) uilabel *namelabel; /** 提示信息 */ @property (nonatomic,strong) uilabel *noticelabel; /** 手機號 */ @property (nonatomic,strong) nsstring *phonenumber; /** 退出按鈕 */ @property (nonatomic,strong) uibutton *quitbtn; @property (nonatomic, strong) wjtouchid *touchid; @end -(instancetype)initwithframe:(cgrect)frame { self = [super initwithframe:ylsscreenbounds]; if (self) { self.backgroundcolor = [uicolor orangecolor]; } //調用指紋解鎖 wjtouchid *touchid = [[wjtouchid alloc]init]; [touchid startwjtouchidwithmessage:wjnotice(@ "自定義信息" , @ "the custom message" ) fallbacktitle:wjnotice(@ "" , @ "fallback title" ) delegate:self]; self.touchid = touchid; return self; } |
第三步
設置控件的位置大小等等屬性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
- ( void )layoutsubviews { [super layoutsubviews]; self.iconview = [[uiimageview alloc]init]; [self.iconview setframe:zlrect(128/320, 54/568, 65/320, 65/568)]; [self.iconview setimage:[uiimage imagenamed:@ "icon_myinformation" ]]; [self addsubview:self.iconview]; self.namelabel = [[uilabel alloc]init]; [self.namelabel setframe:zlrect(0, 125/568, 1, 28/568)]; [self.namelabel settext:@ "151****1234" ]; [self.namelabel setfont:[uifont systemfontofsize:zcfont(15/375)]]; [self.namelabel settextcolor:[uicolor whitecolor]]; [self.namelabel settextalignment:nstextalignmentcenter]; [self addsubview:self.namelabel]; self.touchidbtn = [[uibutton alloc]init]; [self.touchidbtn setframe:zlrect(120/320, 250/568, 80/320, 80/568)]; [self.touchidbtn setimage:[uiimage imagenamed:@ "touchimg" ] forstate:uicontrolstatenormal]; [self.touchidbtn addtarget:self action:@selector(clicktochecktouchid) forcontrolevents:uicontroleventtouchupinside]; [self addsubview:self.touchidbtn]; self.noticelabel = [[uilabel alloc]init]; [self.noticelabel setframe:zlrect(0, 339/568, 1, 22/568)]; [self.noticelabel settext:@ "點擊進行指紋解鎖" ]; [self.noticelabel settextcolor:[uicolor whitecolor]]; [self.noticelabel settextalignment:nstextalignmentcenter]; [self.noticelabel setfont:[uifont systemfontofsize:zcfont(16/375)]]; [self addsubview:self.noticelabel]; self.quitbtn = [[uibutton alloc]init]; [self.quitbtn setframe:zlrect(0, 520/568, 1, 30/568)]; [self.quitbtn settitle:@ "退出" forstate:uicontrolstatenormal]; [self.quitbtn addtarget:self action:@selector(quitcontent) forcontrolevents:uicontroleventtouchupinside]; [self addsubview:self.quitbtn]; } |
第四步
實現控件的點擊方法,以及在.h文件中聲明的彈出方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//快速創建 + (instancetype)touchidview { return [[self alloc]init]; } /** 彈出 */ - ( void )show { [self showinview:[uiapplication sharedapplication].keywindow]; } - ( void )showinview:(uiview *)view { // 浮現 [view addsubview:self]; } -( void )clicktochecktouchid { nslog(@ "點擊了指紋解鎖" ); [self.touchid startwjtouchidwithmessage:wjnotice(@ "自定義信息" , @ "the custom message" ) fallbacktitle:wjnotice(@ "" , @ "fallback title" ) delegate:self]; } -( void )quitcontent { nslog(@ "點擊了quit" ); [uiview animatewithduration:3 animations:^{ self.alpha = 0; } completion:^( bool finished) { [self removefromsuperview]; }]; } |
上面再退出的時候我還加了一個小小的特效,就是顏色漸漸變成無色,這樣有時候可以遮蓋你app里面的一些小問題。偷個懶。
第五步
這里也是跟第一部分一樣,實現驗證的回調函數。這邊的回調函數呢,跟之前的差不多,但是里面的內容就不一樣了。而且我這里把不支持touchid的方法加進來,按理說這邊是不需要加的,但是我前面沒加進來,這里就硬塞進來吧。。。大家就湊合著看,自己用的時候可以直接刪掉,不刪掉也沒事,就是增加點代碼量而已。。。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
/** * touchid驗證成功 */ - ( void ) wjtouchidauthorizesuccess { [mbprogresshud showtext:@ "解鎖成功" view:self]; [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; // [self dismissviewcontrolleranimated:yes completion:nil]; [self removefromsuperview]; } /** * touchid驗證失敗 */ - ( void ) wjtouchidauthorizefailure { [mbprogresshud showtext:@ "解鎖失敗" view:self]; [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 取消touchid驗證 (用戶點擊了取消) */ - ( void ) wjtouchidauthorizeerrorusercancel { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 在驗證的touchid的過程中被系統取消 例如突然來電話、按了home鍵、鎖屏... */ - ( void ) wjtouchidauthorizeerrorsystemcancel { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 無法啟用touchid,設備沒有設置密碼 */ - ( void ) wjtouchidauthorizeerrorpasscodenotset { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 設備沒有錄入touchid,無法啟用touchid */ - ( void ) wjtouchidauthorizeerrortouchidnotenrolled { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 該設備的touchid無效 */ - ( void ) wjtouchidauthorizeerrortouchidnotavailable { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 多次連續使用touch id失敗,touch id被鎖,需要用戶輸入密碼解鎖 */ - ( void ) wjtouchidauthorizelaerrortouchidlockout { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 當前軟件被掛起取消了授權(如突然來了電話,應用進入前臺) */ - ( void ) wjtouchidauthorizelaerrorappcancel { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 當前軟件被掛起取消了授權 (授權過程中,lacontext對象被釋) */ - ( void ) wjtouchidauthorizelaerrorinvalidcontext { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } /** * 當前設備不支持指紋識別 */ -( void )wjtouchidisnotsupport { [[nsuserdefaults standarduserdefaults]setobject:@ "yes" forkey:@ "touchidison" ]; } |
第三部分
這里呢,是最重要的地方,也是最簡單的地方,只要在appdelegate.m文件中加上幾句話就可以實現了。
在下面這個方法里面寫,下面這個方法是呢app被喚醒進入活躍狀態的方法
- (void)applicationdidbecomeactive:(uiapplication *)application
這邊的知識點其實還挺多的,就是一個生命周期的問題,一個app運行完成,即將進入活躍狀態,已經進入活躍狀態,即將進入后臺,已經進入后臺狀態,這幾種狀態,在之前我還想著聲明一個變量讓app在后臺運行的時候,也跟著運行,類似于一個計時器,但是我看了網上的一些想要讓app后臺掛起的時候還能運行一些東西,設置過程就好幾種,而且很多都說上架的時候審核是不給過得,想著有時間的話可以好好研究下那些方法,這里我就沒有弄,所以才有了上面的
[[nsuserdefaults standarduserdefaults]setobject:@"yes" forkey:@"touchidison"];
這個值,本來也是設置成計時器的,但是這樣好像更方便點,就這么設置了,因為為了全局都可以取到這個值。
在喚醒方法中寫下代碼
1
2
3
4
5
6
7
8
9
10
11
12
|
- ( void )applicationdidbecomeactive:(uiapplication *)application { nsstring *touchidexist = [[nsuserdefaults standarduserdefaults]objectforkey:@ "touchid" ]; nsstring *touchison = [[nsuserdefaults standarduserdefaults]objectforkey:@ "touchidison" ]; if ([touchidexist isequaltostring:@ "1" ] && [touchison isequaltostring:@ "no" ]) { ylstouchidview *yls = [[ylstouchidview alloc]init]; [yls show]; } dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(20 * nsec_per_sec)), dispatch_get_main_queue(), ^{ [[nsuserdefaults standarduserdefaults]setobject:@ "no" forkey:@ "touchidison" ]; }); } |
下面那個呢就是為了防止重復調用,因為好像當頁面出現指紋驗證的彈出框的時候,app似乎就是被掛起到后臺了,然后喚醒的時候又要被調用,所以這里出現了一個重復調用的問題,然后我就找個不是辦法的辦法來解決這個問題。就是用上面這段代碼來處理,具體道理我也不知道咋說,就這么迷迷糊糊的實現了功能。這樣子就是完成了一個指紋驗證以及app喚醒的時候指紋解鎖的一個小demo。present出來一個單獨的頁面的方式其實跟這個差不多,但是這篇文章的篇幅好像有點太長了,估計也沒什么人看到最后,所以我就不寫了,啥時候想補的話再補上來吧。
#### 還有就是,本人作為新手,上面代碼有啥問題的話,或者有啥可以優化的地方,希望大家可以指正,大家一起共同進步共同學習。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。