iOS指纹解锁、手势解锁--Swift代码

一、指纹验证

iPhone 的Home键 上的金属环 能感应手指,通知Touch ID 读取指纹,Touch ID 传感器 可以拍摄 皮肤 皮下层指纹。

每次使用指纹,Touch ID 会持续的添加新的指纹特性,进一步提高准确、安全性。

Touch ID 不会储存指纹的图像。它只存储指纹的数学表达式。设备中的芯片还包含称为“Secure Enclave”的高级安全架构,专门用于保护密码和指纹数据。指纹数据通过 Secure Enclave 的专用密钥得到加密和保护。iOS 和其他 app 绝不会访问您的指纹数据,指纹数据绝不会存储到 Apple 服务器、 iCloud 或其他地方。

1、  import LocalAuthentication

2、用 LAContext 类的  canEvaluatePolicy 方法 判断设备是否支持指纹,然后用 evaluatePolicy 方法 来进行指纹验证。

执行evaluatePolicy方法,系统会自动弹出 验证指纹的提示框,提示副标题可以自己设定。

如果输入错误后,系统会自动进入“再试一次”的提示框,点击右边的 “输入密码”选项,要自己写代码实现 输入密码的弹框。

 1         let laContext = LAContext()
 2         var error:NSError?
 3         if laContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) {
 4             laContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics,
 5                                      localizedReason: "请验证已有的指纹",
 6                                      reply: {(success: Bool, error: NSError?) in
 7                 //这里不是在主线程中执行的,是多线程。
 8                 if success {
 9                     print("验证指纹成功")
10                     NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
11                         //主线程刷新View
12                     })
13                 } else {
14                     print(error)
15                     switch error?.code {
16                     case LAError.AuthenticationFailed.rawValue?:
17                         print("授权失败")
18                     case LAError.UserCancel.rawValue?:
19                         print("用户取消验证Touch ID")
20                     case LAError.UserFallback.rawValue?:
21                         print("用户点击 输入密码,切换主线程处理")
22                         NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
23                             self.showPasswordAlert()
24                         })
25                     case LAError.SystemCancel.rawValue?:
26                         print("切换到其他APP,系统取消验证Touch ID")
27                     case LAError.PasscodeNotSet.rawValue?:
28                         print("系统未设置密码")
29                     case LAError.TouchIDNotAvailable.rawValue?:
30                         print("设备Touch ID不可用,例如未打开")
31                     case LAError.TouchIDNotEnrolled.rawValue?:
32                         print("设备Touch ID不可用,用户未录入")
33                     case LAError.TouchIDLockout.rawValue?:
34                         print("Touch ID输入错误多次,已被锁")
35                     case LAError.AppCancel.rawValue?:
36                         print("用户除外的APP挂起,如电话接入等切换到了其他APP")
37                     default:
38                         print("其他情况")
39                         NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
40                             self.showPasswordAlert()
41                         })
42                     }
43                 }
44             })
45
46         } else {
47             print(error)
48         }

Swift Touch ID 代码

二、手势密码

1、用UIButton组成手势的节点。

当手指接触屏幕时,调用重写的 touchesBegan:withEvent方法(在touchesBegan里条用setNeedsDisplay,这样就会自动调用drawRect方法)。

当手指在屏幕上滑动时,调用重写的touchesEnded:withEvent方法。

这两个方法执行的操作是一样的:通过locationInView获取 触摸的坐标,然后用 CGRectContainsPoint 手指是否经过UIButton,如果经过按钮,就更换按钮的图片,同时 保存划过按钮的tag。

默认情况下 跳跃连线第1个和第3个节点,中间的第2个节点 会被忽略,所以要单独进行处理。根据连线 最后2个UIButton的坐标 计算出第1个和第3个节点 中间的坐标,判断该坐标是否存在UIButton,如果存在就加入设置选中,并加入选中数组。

到这里 就已经实现了 手指滑过 节点的时候 节点被选中的效果:

    // MARK: - Override
    // 当手指接触屏幕时,就会调用touchesBegan:withEvent方法;
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        print("执行touchesBegan")
        selectBtnTagArray.removeAll()
        touchesChange(touches)
    }

    //当手指在屏幕上移动时,调用touchesMoved:withEvent方法;
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        touchesChange(touches)
    }

    //当触摸被取消(比如触摸过程中被来电打断),就会调用touchesCancelled:withEvent方法。
    override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {

    }
    //当手指离开屏幕时,就会调用touchesEnded:withEvent方法;
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        print("执行touchesEnded")
        var alertTitle =  "请设置正确的手势"
        var alertMessage = "手势密码不能少于4个"
        var isSuccess = false

        if selectBtnTagArray.count >= 4 {
            alertTitle =  "手势密码设置成功"
            isSuccess = true
            alertMessage = "密码为:\(selectBtnTagArray)"
        }

        gestureLockDelegate!.gestureLockSuccess(isSuccess, title: alertTitle, message: alertMessage)

        gesturePoint = CGPointZero;
        self.setNeedsDisplay()
    }

    // MARK: - PrivateMethod
    private func initButtons() {
        for i in 0...8 {
            //第几行
            let row = i / 3
            let loc = i % 3

            //两个button的间距
            let btnSpace = (screenWidth - 3*btnWH)/4
            let btnX = btnSpace + (btnWH + btnSpace) * CGFloat(loc)
            let btnY = 70 + btnSpace + (btnWH + btnSpace) * CGFloat(row)

            let gestureNodeBtn = UIButton(frame:CGRectMake(btnX, btnY, btnWH, btnWH))
            gestureNodeBtn.tag = i
            gestureNodeBtn.userInteractionEnabled = false   //不响应用户的交互。一定要加上这句
            gestureNodeBtn.setImage(UIImage(named: btnImgNormal), forState: .Normal)
            self.addSubview(gestureNodeBtn)
            btnArray.append(gestureNodeBtn)
        }
    }

    private func touchesChange(touches: Set<UITouch>) {
        //获取 触摸对象 ,触摸对象的位置坐标来实现
        gesturePoint = touches.first!.locationInView(self)

        for btn in btnArray {
            //判断 手指的坐标 是否在 button的坐标里
            if !selectBtnTagArray.contains(btn.tag) && CGRectContainsPoint(btn.frame, gesturePoint) {
                //处理跳跃连线
                var lineCenterPoint:CGPoint = CGPoint()

                if selectBtnTagArray.count > 0 {
                    lineCenterPoint = centerPoint(btn.frame.origin, endPoint: btnArray[selectBtnTagArray.last!].frame.origin)
                }

                //保存中间跳跃 过的节点
                for btn in btnArray {
                    if  !selectBtnTagArray.contains(btn.tag) && CGRectContainsPoint(btn.frame, lineCenterPoint)  {
                        btn.setImage(UIImage(named: btnImgSelected), forState: .Normal)
                        selectBtnTagArray.append(btn.tag)
                    }
                }

                //保存划过的按钮的tag
                selectBtnTagArray.append(btn.tag)
                btn.setImage(UIImage(named: btnImgSelected), forState: .Normal)
            }
        }

        //setNeedsDisplay会自动调用drawRect方法 进行画线
        self.setNeedsDisplay()
    }

    //计算2个节点中心的坐标
    private func centerPoint(startPoint: CGPoint, endPoint:CGPoint) -> CGPoint {
        let rightPoint = startPoint.x > endPoint.x ? startPoint.x : endPoint.x
        let leftPoint = startPoint.x < endPoint.x ? startPoint.x : endPoint.x

        let topPoint = startPoint.y > endPoint.y ? startPoint.y : endPoint.y
        let bottomPoint = startPoint.y < endPoint.y ? startPoint.y : endPoint.y

        //x坐标: leftPoint +(rightPoint-leftPoint)/2 = (rightPoint+leftPoint)/2
        return CGPointMake((rightPoint + leftPoint)/2 + btnWH/2, (topPoint + bottomPoint)/2 + btnWH/2);
    }

    func recoverNodeStatus() {
        selectBtnTagArray.removeAll()
        for btn in btnArray {
            btn.setImage(UIImage(named: btnImgNormal), forState: .Normal)
        }
        self.setNeedsDisplay()
    }
    

2、画线:在drawRect方法中进行画线。

    override func drawRect(rect: CGRect) {
        print("执行drawRect")
        let context = UIGraphicsGetCurrentContext() //获取画笔上下文

        var i = 0
        for tag in selectBtnTagArray {
            if (0 == i) {
                //开始画线,设置直线的起点坐标
                CGContextMoveToPoint(context, btnArray[tag].center.x, btnArray[tag].center.y)
            } else {
                //画直线,设置直线的终点坐标
                CGContextAddLineToPoint(context, btnArray[tag].center.x,btnArray[tag].center.y)
            }
            i = i+1
        }

        //如果有选中的节点,就取 跟着 手指的滑动 画线
        if (selectBtnTagArray.count > 0) {
            // 移除最后一条多余的线,
            if gesturePoint != CGPointZero {
                CGContextAddLineToPoint(context, gesturePoint.x, gesturePoint.y)
            }
        }

        CGContextSetLineWidth(context, 10)      //设置画笔宽度
        CGContextSetLineJoin(context, .Round)   //两个线相交点 平滑处理
        CGContextSetLineCap(context, .Round)    //设置线条两端的样式为圆角
        CGContextSetRGBStrokeColor(context, 227/255.0, 54/255.0, 58/255.0, 1)
        CGContextStrokePath(context)            // //对线条进行渲染
    }

Demo地址:https://github.com/bugaoshuni/TouchIDAndGestureLock

时间: 2024-08-04 16:26:58

iOS指纹解锁、手势解锁--Swift代码的相关文章

iOS开发之手势解锁

本文主要介绍通过手势识别实现手势解锁功能,这个方法被广泛用于手机解锁,密码验证,快捷支付等功能实现.事例效果如下所示. 首先,我们先分析功能的实现过程,首先我们需要先看大致的实现过程: 1.加载九宫格页面 2.实现按钮被点击及滑动过程中按钮状态的改变 3.实现滑动过程中的连线 4.绘制完毕后判定密码是否正确, 5.密码判定后实现跳转. 下面我们就来用代码实现上述五个过程. 1.加载九宫格界面 1.1九宫格内控件的分布 3*3 ,我们可以自定义view(包含3*3个按钮),添加到viewContr

iOS仿安卓手势解锁

界面是一个九宫格的布局.九宫格实现思路. 先确定有多少列 cloum = 3; 计算出每列之间的距离 计算为: CGFloat margin = (当前View的宽度 - 列数 * 按钮的宽度) / 总列数 + 1 每一列的X的值与它当前所在的行有关 当前所在的列为:curColum = i % cloum 每一行的Y的值与它当前所在的行有关. 当前所在的行为:curRow = i / cloum 每一个按钮的X值为, margin + 当前所在的列 * (按钮的宽度+ 每个按钮之间的间距) 每

iOS开发_手势解锁

创建一个继承于UIView的子类如下: 头文件ZRLockView.h 1 ZRLockView.h 2 3 #import <UIKit/UIKit.h> 4 5 @class ZRLockView; 6 7 @protocol ZRLockViewDelegate <NSObject> 8 9 @optional 10 -(void)lockView:(ZRLockView *)lockView didFinishPath:(NSString *)path; 11 12 @en

在iOS上增加手势锁屏、解锁功能

在iOS上增加手势锁屏.解锁功能 在一些涉及个人隐私的场景下,尤其是当移动设备包含太多私密信息时,为用户的安全考虑是有必要的. 桌面版的QQ在很多年前就考虑到用户离开电脑后隐私泄露的危险,提供了“离开电脑自动锁定”或者“闲置锁定”等类似功能,具体我也忘了. 而在iPhone版的QQ上,也提供了手势锁的功能.如下图: 我在上一篇博文中简单提到如何根据手指移动画线条,而这里是进一步的版本,仍然只是粗糙原型: 具体的代码实现如下: [cpp]  //  //  ViewController.m  //

iOS开发UI篇—实现一个简单的手势解锁应用(基本)

iOS开发UI篇—实现一个简单的手势解锁应用(基本) 一.实现效果 实现效果图: 二.手势解锁应用分析 1.监听手指在view上的移动,首先肯定需要自定义一个view,重写touch began,touch move等方法,当手指移动到圈上时,让其变亮.可以通过button按钮来实现. 2.界面搭建 背景图片(给控制器的view添加一个imageview,设置属性背景图片) 九个按钮(把九个按钮作为一个整体,使用一个大的view来管理这些小的view,这些小的view就是9个button.如果使

iOS开发UI篇—实现一个简单的手势解锁应用(完善)

iOS开发UI篇—实现一个简单的手势解锁应用(完善) 一.需要实现的效果 二.应用完善 1.绘制不处于按钮范围内的连线 2.解决bug(完善) bug1:如果在began方法中通知view绘图,那么会产生bug.因为,当前点没有清空,在手指移开之后要清空当前点.可以在绘制前进行判断,如果当前点是(0,0)那么就不划线.或者在began方法中不进行重绘. bug2:无限菊花.自定义view的背景色为默认的(黑色),只要重写了drawrect方法,view默认的背景颜色就是黑色的,因为上下文默认的颜

Swift实现手势解锁&amp;界面跳转&amp;读取SQLite数据库

按钮是根据屏幕大小自动布局,所以不会因为设备不同导致错位 数据库操作是GitHub上的SQLiteDB 下面是Storyboard的设计图 下面是实现的代码 // // ViewController.swift // // // Created by XWJACK on 15/12/15. // Copyright © 2015年 XWJACK. All rights reserved. // import UIKit class ViewController: UIViewController

(素材源码)猫猫学IOS(三十五)UI之Quartz2D仿真支付宝手势解锁_代理获得密码。

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 源码:http://download.csdn.net/detail/u013357243/8669765 效果: 代码: NYLockView.h // // NYLockView.h // 手势解锁 // // Created by apple on 15-5-6. // Copyright (c) 2015年 znyca

【iOS开发之旅】手势解锁

BOERLockView.h // // BOERLockView.h // BoerScore // // Created by ChenQianPing on 16/2/18. // Copyright © 2016年 boer. All rights reserved. // #import <UIKit/UIKit.h> @class BOERLockView; @protocol BOERLockViewDelegate <NSObject> // 结束手势解锁代理事件

iOS绘制手势解锁密码

手势解锁这个功能其实已经用的越来越少了.但是郁闷不知道我公司为什么每次做一个app都要把手势解锁加上.....于是就自己研究了一下手势解锁页面的实现.. 要想实现这个页面,先说说需要掌握哪些: UIPanGestureRecognizer的基本使用 CGRectContainsPoint(<#CGRect rect#>, <#CGPoint point#>) UIBezierPath贝塞尔曲线的绘制 drawRect 和 layoutIfNeeded 知道何时,如何使用 只要掌握上