1. 需求说明:我的页面显示一个指纹登录的开关,当用户设置指纹登录开关开启的之后,用户下次登录在登录页面可以使用指纹进行登录,当开关关闭,则用户登录只能使用用户名,密码进行登录。使用指纹登录时需要进行校验,当指纹不匹配,未开启指纹或设备不支持指纹登录,或者多次校验失败时,需要输入解锁密码进行解锁。
2.实现代码 我的—>设置界面
// 设置是指纹登录开关显示并关联指纹登录方法
(1)cellForRow的方法中:
```
let fingerCell:FingerPrintTableViewCell? = tableview.dequeueReusableCell(withIdentifier: fingerPrintIdentifier) as? FingerPrintTableViewCell
// 更新指纹登录开关状态
if let isOn = UserDefaults.standard.object(forKey: kUseTouchID) as? Bool {
fingerCell?.chooseSwitch.isOn = isOn
} else {
fingerCell?.chooseSwitch.isOn = false
}
//changeTouchID为
fingerCell?.chooseSwitch.addTarget(self, action: #selector(changeTouchID(_:)), for: .valueChanged)
fingerCell?.selectionStyle = .none
return fingerCell!
```
(2)在changeTouchID中指根据开关状态分别调用指纹开启于关闭的方法
@objc fileprivate func changeTouchID(_ sw: UISwitch) {
if sw.isOn {
// 打开操作
debugPrint("打开操作")
self.switchIsOn(sw: sw)
}
else
{
// 关闭操作
debugPrint("关闭操作")
self.switchIsOff(sw: sw)
}
}
(3)开启指纹方法
//验证指
func switchIsOn(sw: UISwitch)
{
let context = LAContext()
var message = ""
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "通过Home键验证已有的手机指纹", reply: { (success, authenticationError) in
if success == true {
// 校验成功
message = "打开成功"
UserDefaults.standard.set(true, forKey: kUseTouchID)
UserDefaults.standard.synchronize()
DispatchQueue.main.async {
sw.isOn = true
}
} else {
// 校验失败
/// 取消:Canceled by user.
/// 未开启或设备不支持:No fingers are enrolled with Touch ID.
// 多次校验失败 desc String? "Biometry is locked out." some
let desc = authenticationError?.localizedDescription
if desc?.contains("Canceled") == true {
message = ""
}else if desc?.contains("retry limit exceeded") == true {
// 提示校验失败
message = "指纹不匹配"
}else if desc?.contains("Biometry is") == true {
// 多次校验失败,弹出用户输入密码解锁
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "请输入解锁密码", reply: { (success, error) in
if success == true {
// 密码校验成功
debugPrint("密码校验成功")
self.switchIsOn(sw: sw)
} else {
// 密码校验失败
debugPrint("密码校验失败")
}
})
}else {
message = "您未开启指纹功能"
}
DispatchQueue.main.async {
sw.isOn = false
}
}
if message.characters.count > 0 {
DispatchQueue.main.async {
SVProgressHUD.showInfo(withStatus: message)
SVProgressHUD.dismiss(withDelay: 1)
}
}
debugPrint(message)
})
}
(4)关闭指纹方法
func switchIsOff(sw: UISwitch)
{
let context = LAContext()
var message = ""
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "通过Home键验证已有的手机指纹", reply: { (success, authenticationError) in
if success == true {
// 校验成功
message = "关闭成功"
UserDefaults.standard.set(false, forKey: kUseTouchID)
UserDefaults.standard.synchronize()
DispatchQueue.main.async {
sw.isOn = false
}
} else {
// 校验失败
/// 取消:Canceled by user.
/// 未开启或设备不支持:No fingers are enrolled with Touch ID.
// 多次校验失败 desc String? "Biometry is locked out." some
let desc = authenticationError?.localizedDescription
if desc?.contains("Canceled") == true {
message = ""
}else if desc?.contains("retry limit exceeded") == true {
// 提示校验失败
message = "指纹不匹配"
}else if desc?.contains("Biometry is") == true {
// 多次校验失败,弹出用户输入密码解锁
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "请输入解锁密码", reply: { (success, error) in
if success == true {
// 密码校验成功
debugPrint("密码校验成功")
self.switchIsOff(sw: sw)
} else {
// 密码校验失败
debugPrint("密码校验失败")
}
})
}else {
message = "指纹关闭失败"
}
DispatchQueue.main.async {
sw.isOn = true
}
}
if message.characters.count > 0 {
DispatchQueue.main.async {
SVProgressHUD.showInfo(withStatus: message)
SVProgressHUD.dismiss(withDelay: 1)
}
}
debugPrint(message)
})
}
到此我的界面指纹开启与关闭可以自由切换 ,下面根据“我的”界面的设置完成登录界面是否展示使用指纹登录
(1)在viewWillAppear通过指纹UserDefaults取出指纹开关状态,从而设置开启指纹登录按钮是否显示
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let isTouchID = UserDefaults.standard.object(forKey: kUseTouchID) as? Bool {
if isTouchID == true {
// 开启指纹
self.startFinger()
self.fingerBtn.isHidden = false
} else {
self.fingerBtn.isHidden = true
}
} else {
self.fingerBtn.isHidden = true
}
}
(2)登录界面开启指纹登录方法(原理与“我的界面相同”)
func startFinger()
{
var message = ""
let context = LAContext()
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "通过Home键验证已有的手机指纹", reply: { [weak self] (success, authenticationError) in
if success == true {
// 校验成功
self?.autoLogin()
} else {
// 提示
// 校验失败
/// 取消:Canceled by user.
/// 未开启或设备不支持:No fingers are enrolled with Touch ID.
// 三次校验失败:Application retry limit exceeded
// 多次校验失败:"Biometry is locked out."
// Biometry is not available in passcode lockout
let desc = authenticationError?.localizedDescription
if desc?.contains("Canceled") == true {
message = ""
} else if desc?.contains("Biometry is") == true {
// 多次校验失败,弹出用户输入密码解锁
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "请输入解锁密码", reply: { (success, error) in
if success == true {
// 密码校验成功
debugPrint("密码校验成功")
self?.startFinger()
} else {
// 密码校验失败
debugPrint("密码校验失败")
}
})
} else if desc?.contains("retry limit exceeded") == true {
// 提示校验失败
message = "指纹不匹配"
}
}
if message.characters.count > 0 {
DispatchQueue.main.async {
SVProgressHUD.showInfo(withStatus: message)
SVProgressHUD.dismiss(withDelay: 1)
}
}
})
}
注意:在我的界面从本地取出开关状态的时候swift与oc 有个明显的区别,let isOn = UserDefaults.standard.object(forKey: kUseTouchID) as? Bool swift在转换类型前得到的是一个 AnyObject此时我们理所当然转换为bool类型从而进行判断,而oc返回值已为bool类型,但是我们仍应用boolvalue进行转化,因为oc中未加boolvalue前 我们得到的bool值是通过NSUserDefaults通过key在本地的取值,如果有值,则返回yes,如果无值,则返回no,这不是开关真实的状态,所以一定要加boolvalue进行强转!
let lineView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: ScreenWidth, height: lineViewHeight))