项目说明
初次打开设置并确认手势密码,超过五次后重置
在设置中修改手势密码
APP退至后台10S后需要手势密码解锁进入
思路
- window的根视图是mainVC,在mainVC中设置完主控制器后,添加gestureView(手势密码)
- 在gestureView中
通过UIButton,UIBezierPath,数组和变量实现手势密码绘制
手势按钮即9个button,上面有个messageLabel
非修改手势密码思路
不移除self.path所有点就会这样
将按钮颜色去掉会发现,当path.move时,当前点不会多余线,但当path.addLine时,则结束时会记录下你划过的方向
修改手势密码思路
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