1. 需求說明:我的頁面顯示一個指紋登錄的開關,當用戶設置指紋登錄開關開啟的之后,用戶下次登錄在登錄頁面可以使用指紋進行登錄,當開關關閉,則用戶登錄只能使用用戶名,密碼進行登錄。使用指紋登錄時需要進行校驗,當指紋不匹配,未開啟指紋或設備不支持指紋登錄,或者多次校驗失敗時,需要輸入解鎖密碼進行解鎖。
2.實現(xiàn)代碼 我的—>設置界面
// 設置是指紋登錄開關顯示并關聯(lián)指紋登錄方法
(1)cellForRow的方法中:
```
let fingerCell:FingerPrintTableViewCell?? = tableview.dequeueReusableCell(withIdentifier: fingerPrintIdentifier) as? FingerPrintTableViewCell
// 更新指紋登錄開關狀態(tài)
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中指根據(jù)開關狀態(tài)分別調(diào)用指紋開啟于關閉的方法
@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)
})
}
到此我的界面指紋開啟與關閉可以自由切換 ,下面根據(jù)“我的”界面的設置完成登錄界面是否展示使用指紋登錄
(1)在viewWillAppear通過指紋UserDefaults取出指紋開關狀態(tài),從而設置開啟指紋登錄按鈕是否顯示
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.
// 三次校驗失?。篈pplication 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)
}
}
})
}
注意:在我的界面從本地取出開關狀態(tài)的時候swift與oc 有個明顯的區(qū)別,let isOn = UserDefaults.standard.object(forKey: kUseTouchID) as? Bool ? ? ? swift在轉(zhuǎn)換類型前得到的是一個 AnyObject此時我們理所當然轉(zhuǎn)換為bool類型從而進行判斷,而oc返回值已為bool類型,但是我們?nèi)詰胋oolvalue進行轉(zhuǎn)化,因為oc中未加boolvalue前 我們得到的bool值是通過NSUserDefaults通過key在本地的取值,如果有值,則返回yes,如果無值,則返回no,這不是開關真實的狀態(tài),所以一定要加boolvalue進行強轉(zhuǎn)!
let lineView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: ScreenWidth, height: lineViewHeight))