美文网首页iOS备忘录iOS 开发 iOS学习开发
iOS学习笔记15 指纹验证TouchID简单应用2

iOS学习笔记15 指纹验证TouchID简单应用2

作者: 点柈 | 来源:发表于2016-08-08 22:19 被阅读193次

        上一篇文章简单的写了对于touchid的简单了解。因为太懒了,就没有写实例,现在就单独写一篇应用吧,这篇想做的就是一个模仿那个叫啥软件来着,某某理财类类的软件的一个指纹验证解锁。我们做出来的页面应该如下图,在app挂起到后台的时候再点击到前台的时候回出现如下页面:

    app唤醒的时候出现的画面 点击取消按钮出现的页面
        这里我先挂上github的链接地址,毕竟本文的篇幅较长,也没什么人有耐心有时间看到最后,顶多看下demo,快速的知道怎么调用啥的就可以了。popViewForTouchID
        因为我之前没遇到个这种情况,所以我做的都是自己瞎搞搞出来的,也不知道平时大家做的时候是怎么做的,就搞出来这样的,这里我打算用两种方法来实现,不过这个东西放进app中貌似是需要适配的。还是有些许问题的。可能要调下。
        在app被唤醒的时候,出现页面我用了两种方式,一种是present出来一个单独的页面,一种方式是自定义弹出view。
        但是本文呢,主要就介绍一下弹出式view的方式,因为present的方式跟这种方式差别就是在于一个是view一个是Controller,主要的思想还是一样的。

    第一部分

    第一步

        引入需要用的文件,以及创建pch文件,因为是小demo,所以一些宏定义直接丢进去就可以了。


    指纹验证和信息显示控件

    第二步

        创建pch文件,引入一些需要用到的文件以及宏定义,这里要是有问题的话可以参照我之前一篇文章写的引入pch文件,当然也可以老老实实的每个文件里都去引入头文件啥的,这个很随意的,毕竟是demo。

    #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
    

    第三步

        实现基础页面,如下图


    基础页面
    • 声明变量,遵守指纹验证控件的协议
    @interface ViewController ()<WJTouchIDDelegate>
    /** NoticeLabel */
    @property (nonatomic,strong) UILabel *label;
    /** UISwitch */
    @property (nonatomic,strong) UISwitch *touchIDSwitch;
    
    @property (nonatomic, strong) WJTouchID *touchID;
    @end
    
    • 懒加载
    -(UISwitch *)touchIDSwitch
    {
        if (!_touchIDSwitch)
        {
            self.touchIDSwitch = [[UISwitch alloc]init];
        }
        return _touchIDSwitch;
    }
    
    
    • 添加子控件
    -(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方法中调用设置子控件的方法,并且实现开关切换的方法。

    - (void)viewDidLoad {
        [super viewDidLoad];
        [self setSubViews];
    }
    

        切换方法里呢,就是需要调用者会问验证,一般软件设置指纹验证的时候都会要求你先验证一下子,我在这里设置成只要你开或关闭都需要验证一下。

    -(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;
    }
    

    第五步

        在上述调用指纹验证成功后,必须得实现它的回调函数,在成功或者失败的方法中写上你需要执行的代码。

    //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文件中写入方法

    @interface YLSTouchidView : UIView
    
    /**
     *  快速创建
     */
    +(instancetype)touchIDView;
    
    /**
     *  弹出
     */
    -(void)show;
    -(void)showInView:(UIView *)view;
    
    @end
    
    

    第二步

        在.m文件中声明控件,设置页面大小,以及遵守协议,在页面出来的同时就要调用验证服务。

    @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;
    }
    

    第三步

        设置控件的位置大小等等属性。

    - (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文件中声明的弹出方法

    //快速创建
    + (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的方法加进来,按理说这边是不需要加的,但是我前面没加进来,这里就硬塞进来吧。。。大家就凑合着看,自己用的时候可以直接删掉,不删掉也没事,就是增加点代码量而已。。。

    /**
     *  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"];
    

        这个值,本来也是设置成计时器的,但是这样好像更方便点,就这么设置了,因为为了全局都可以取到这个值。
    在唤醒方法中写下代码

    - (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出来一个单独的页面的方式其实跟这个差不多,但是这篇文章的篇幅好像有点太长了,估计也没什么人看到最后,所以我就不写了,啥时候想补的话再补上来吧。

    还有就是,本人作为新手,上面代码有啥问题的话,或者有啥可以优化的地方,希望大家可以指正,可以了留言跟我讨论,或者是私信啥的,都可以,大家一起共同进步共同学习。

    相关文章

      网友评论

        本文标题:iOS学习笔记15 指纹验证TouchID简单应用2

        本文链接:https://www.haomeiwen.com/subject/pzmrsttx.html