【Swift3】手势密码

项目说明

初次打开设置并确认手势密码,超过五次后重置
在设置中修改手势密码
APP退至后台10S后需要手势密码解锁进入

思路

  • window的根视图是mainVC,在mainVC中设置完主控制器后,添加gestureView(手势密码)
  • 在gestureView中
    通过UIButton,UIBezierPath,数组和变量实现手势密码绘制
    手势按钮即9个button,上面有个messageLabel
【Swift3】手势密码_第1张图片
非修改手势密码思路
【Swift3】手势密码_第2张图片
【Swift3】手势密码_第3张图片
【Swift3】手势密码_第4张图片

不移除self.path所有点就会这样


【Swift3】手势密码_第5张图片

将按钮颜色去掉会发现,当path.move时,当前点不会多余线,但当path.addLine时,则结束时会记录下你划过的方向


【Swift3】手势密码_第6张图片
【Swift3】手势密码_第7张图片
修改手势密码思路
【Swift3】手势密码_第8张图片
gestureView主要代码如下
import UIKit

class GestureView: UIView
{
    //初次登陆时候的最多输入次数
    var inputCount:Int = 0
    //控制是否初次登陆
    var isFirst:Bool = true
    //控制是否修改密码
    var isChangeGestures:Bool = false
    
    //路径
    var path:UIBezierPath = UIBezierPath()
    //存储已经路过的点
    var pointsArray = [CGPoint]()
    //当前手指所在点
    var fingurePoint:CGPoint!
    //密码存储
    var passwordArray = [Int]()
    
    
    //MARK: - Override
    override init(frame: CGRect)
    {
        super.init(frame: frame)
        layoutUI()
    }
    
    required init?(coder aDecoder: NSCoder)
    {
        fatalError("init(coder:) has not been implemented")
    }
    
    init(frame: CGRect,changeGestures:Bool)
    {
        super.init(frame: frame)
        isChangeGestures = changeGestures
        layoutUI()
    }
    
    
    //MARK: - 懒加载
    lazy var messageLabel : UILabel =
    {
        let label = UILabel()
        label.textColor = UIColor.darkGray
        label.textAlignment = NSTextAlignment.center
        return label
    }()
    
    //MARK: - UI
    func layoutUI()
    {
        self.backgroundColor = UIColor.white
        //添加提示框
        addSubview(messageLabel)
        messageLabel.frame = CGRect(x: 0, y: 100, width: ScreenWidth, height: 50)
        //添加手势密码
        gesturePasswordUI()
        //设置path
        path.lineWidth = 2
        
        //是否修改密码
        if isChangeGestures
        {
            print("这是修改密码界面")
            UserDefaults.standard.removeObject(forKey: "newPassWord")
            messageLabel.text = "请输入新的手势密码"
            
        }
        else
        {
            print("不是修改密码界面")
            //本地密码
            let passWord = UserDefaults.standard.value(forKey: "passWord")
            if(passWord != nil)
            {
                isFirst = false
                messageLabel.text = "确认手势密码"
            }
            else
            {
                messageLabel.text = "请创建手势密码"
            }
        }
        

    }
    
    func gesturePasswordUI()
    {
        //画密码
        let width:CGFloat = 60.0
        let height:CGFloat = width
        var x:CGFloat = 0
        var y:CGFloat = 0
        //计算空隙
        let spaceWidth = (ScreenWidth - 3 * width) / 4
        let spaceHeight = (ScreenHeight - 3 * height) / 4
        for index in 0..<9
        {
            //计算当前所在行
            let row = index % 3
            let line = index / 3
            //计算坐标
            x = CGFloat(row) * width + CGFloat(row + 1) * spaceWidth
            y = CGFloat(100 * line) + spaceHeight * 2
            let button = NumberButton(frame: CGRect(x: x, y: y, width: width, height: height))
            button.tag = index
            addSubview(button)
        }
    }

    
    
    //MARK: - Other Functions
    override func touchesBegan(_ touches: Set, with event: UIEvent?)
    {
        //每次点击移除所有存储过的点,重新统计
        pointsArray.removeAll()
        touchChanged(touch: touches.first!)
    }
    
    
    override func touchesMoved(_ touches: Set, with event: UIEvent?)
    {
        touchChanged(touch: touches.first!)
    }
    
    func touchChanged(touch:UITouch)
    {
        let point = touch.location(in: self)
        fingurePoint = point
        for button in subviews
        {
            if button.isKind(of: NumberButton.self) && !pointsArray.contains(button.center) && button.frame.contains(fingurePoint)
            {
                //记录已经走过的点
                passwordArray.append(button.tag)
                //记录密码
                pointsArray.append(button.center)
                //设置按钮的背景色
                button.backgroundColor = UIColor.hexStringToColor(hexString: ColorOfBlueColor)
            }
            
        }
        //会调用draw 方法
        setNeedsDisplay()
    }
    
    override func draw(_ rect: CGRect)
    {
        self.path.removeAllPoints()
        for (index,point) in pointsArray.enumerated()
        {
            if index == 0
            {
                path.move(to: point)
            }
            else
            {
                path.addLine(to: point)
            }
            
        }
        //让画线跟随手指
        if self.fingurePoint != CGPoint.zero && self.pointsArray.count > 0
        {
            path.addLine(to: self.fingurePoint)
        }
        
        //设置线的颜色
        let color = UIColor.hexStringToColor(hexString: ColorOfBlueColor)
        color.set()
        path.stroke()
    }
    
    
    //松手的时候调用
    override func touchesEnded(_ touches: Set, with event: UIEvent?)
    {
        if(passwordArray as NSArray).count == 0
        {
            return
        }
        inputCount += 1
        
        //本地存储
        let passWord = UserDefaults.standard.value(forKey: "passWord")
        let newPassWord = UserDefaults.standard.value(forKey: "newPassWord")
        //修改密码界面
        if isChangeGestures
        {
            if(newPassWord != nil )
            {
                if Tools().passwordString(array: passwordArray as NSArray) == Tools().passwordString(array: newPassWord as! NSArray)
                {
                    messageLabel.text = "设置成功"
                    isHidden = true
                    UserDefaults.standard.set(passwordArray, forKey: "passWord")
                }
                else
                {
                    if inputCount < 5
                    {
                        messageLabel.text = "输入错误,还可以输入\(5 - inputCount)次"
                    }
                    else
                    {
                        messageLabel.text = "请重置手势密码"
                        inputCount = 0
                        UserDefaults.standard.removeObject(forKey: "newPassWord")
                    }
                    
                }

            }
            else//初次储存新密码
            {
                UserDefaults.standard.set(passwordArray, forKey: "newPassWord")
            }
            
        }
        //非修改密码界面
        else
        {
            //初次登陆,五次设置密码的机会
            if isFirst
            {
                if(passWord != nil && (passWord as! NSArray).count > 0)
                {
                    if Tools().passwordString(array: passwordArray as NSArray) == Tools().passwordString(array: passWord as! NSArray)
                    {
                        messageLabel.text = "设置成功"
                        isHidden = true
                    }
                    else
                    {
                        if inputCount < 5
                        {
                            messageLabel.text = "输入错误,还可以输入\(5 - inputCount)次"
                        }
                        else
                        {
                            messageLabel.text = "请重置手势密码"
                            inputCount = 0
                            UserDefaults.standard.removeObject(forKey: "passWord")
                        }
                        
                    }
                }
                else//初次存储
                {
                    messageLabel.text = "确认手势密码"
                    UserDefaults.standard.set(passwordArray, forKey: "passWord")
                }
                
            }
            else//非初次登陆,不可重置密码,只能一直输入
            {
                if Tools().passwordString(array: passwordArray as NSArray) == Tools().passwordString(array: passWord as! NSArray)
                {
                    isHidden = true
                }
                else
                {
                    messageLabel.text = "输入错误"
                    
                }
                
            }
        }
        
        //移除所有的记录
        pointsArray.removeAll()
        passwordArray.removeAll()
        path.removeAllPoints()
        setNeedsDisplay()
        fingurePoint = CGPoint.zero
        
        //清除所有按钮的选中状态
        for button in subviews
        {
            if button.isKind(of: NumberButton.self)
            {
                button.backgroundColor  =  UIColor.clear
            }
        }
        
    }
}

APP退至后台10S后需要手势密码解锁进入

当APP进入后台时记录当前时间
当APP进入前台时记录当前时间
如果这两个时间差大于10S,则显示gestureView界面,并且设置gestureView的isFirst等于false(证明不是初次设置),并且设置gestureView的messageLabel显示"确认手势密码"

    //进入后台
    func applicationDidEnterBackground(_ application: UIApplication)
    {
        let now = Date()
        let timeInterval:TimeInterval = now.timeIntervalSince1970
        let timeStamp = Int(timeInterval)
        UserDefaults.standard.set(timeStamp, forKey: "currentTime")
    }
    
    //进入前台
    func applicationWillEnterForeground(_ application: UIApplication)
    {
        let now = Date()
        let timeInterval:TimeInterval = now.timeIntervalSince1970
        let timeStamp = Int(timeInterval)
        let currentTime = UserDefaults.standard.value(forKey: "currentTime")
        if (timeStamp - (currentTime as! Int)) > 10
        {
            //超过10S则显示手势密码
            mainVC.gestureView.isHidden = false
            mainVC.gestureView.isFirst = false
            mainVC.gestureView.messageLabel.text = "确认手势密码"
        }
    }

但是因为设置的二级界面调用了gestureView,若此时APP退至后台,再回前台,指纹解锁后进来还是指纹解锁,用户体验不好,所以应该监听APP的进入后台的方法,当程序进入后台的时候,我们应该让设置界面的gestureView移除

在基类中添加消息,并且实现消息
import UIKit

class BaseViewController: UIViewController
{

    override func viewDidLoad()
    {
        super.viewDidLoad()
        //监听程序挂起消息
        NotificationCenter.default.addObserver(self, selector: #selector(test), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
    }
    
    func test()
    {
        print("后台挂起")
    }

}

在设置控制器中重写消息的实现方法,如果APP退出后台了,会自己调用
    override func test()
    {
        gestureView?.removeFromSuperview()
    }

Demo地址:
https://github.com/CarolineQian/FQGesturesPassword

你可能感兴趣的:(【Swift3】手势密码)