1. 需求說明:我的頁面顯示一個(gè)指紋登錄的開關(guān)女蜈,當(dāng)用戶設(shè)置指紋登錄開關(guān)開啟的之后滔悉,用戶下次登錄在登錄頁面可以使用指紋進(jìn)行登錄型凳,當(dāng)開關(guān)關(guān)閉,則用戶登錄只能使用用戶名流酬,密碼進(jìn)行登錄币厕。使用指紋登錄時(shí)需要進(jìn)行校驗(yàn),當(dāng)指紋不匹配芽腾,未開啟指紋或設(shè)備不支持指紋登錄旦装,或者多次校驗(yàn)失敗時(shí),需要輸入解鎖密碼進(jìn)行解鎖摊滔。
2.實(shí)現(xiàn)代碼 我的—>設(shè)置界面
// 設(shè)置是指紋登錄開關(guān)顯示并關(guān)聯(lián)指紋登錄方法
(1)cellForRow的方法中:
```
let fingerCell:FingerPrintTableViewCell?? = tableview.dequeueReusableCell(withIdentifier: fingerPrintIdentifier) as? FingerPrintTableViewCell
// 更新指紋登錄開關(guān)狀態(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ù)開關(guān)狀態(tài)分別調(diào)用指紋開啟于關(guān)閉的方法
@objc fileprivate func changeTouchID(_ sw: UISwitch) {
if sw.isOn {
// 打開操作
debugPrint("打開操作")
self.switchIsOn(sw: sw)
}
else
{
// 關(guān)閉操作
debugPrint("關(guān)閉操作")
self.switchIsOff(sw: sw)
}
}
(3)開啟指紋方法
//驗(yàn)證指
func switchIsOn(sw: UISwitch)
{
let context = LAContext()
var message = ""
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "通過Home鍵驗(yàn)證已有的手機(jī)指紋", reply: { (success, authenticationError) in
if success == true {
// 校驗(yàn)成功
message = "打開成功"
UserDefaults.standard.set(true, forKey: kUseTouchID)
UserDefaults.standard.synchronize()
DispatchQueue.main.async {
sw.isOn = true
}
} else {
// 校驗(yàn)失敗
/// 取消:Canceled by user.
/// 未開啟或設(shè)備不支持:No fingers are enrolled with Touch ID.
// 多次校驗(yàn)失敗? ? 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 {
// 提示校驗(yàn)失敗
message = "指紋不匹配"
}else if desc?.contains("Biometry is") == true {
// 多次校驗(yàn)失敗阴绢,彈出用戶輸入密碼解鎖
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "請(qǐng)輸入解鎖密碼", reply: { (success, error) in
if success == true {
// 密碼校驗(yàn)成功
debugPrint("密碼校驗(yàn)成功")
self.switchIsOn(sw: sw)
} else {
// 密碼校驗(yàn)失敗
debugPrint("密碼校驗(yàn)失敗")
}
})
}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)關(guān)閉指紋方法
func switchIsOff(sw: UISwitch)
{
let context = LAContext()
var message = ""
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "通過Home鍵驗(yàn)證已有的手機(jī)指紋", reply: { (success, authenticationError) in
if success == true {
// 校驗(yàn)成功
message = "關(guān)閉成功"
UserDefaults.standard.set(false, forKey: kUseTouchID)
UserDefaults.standard.synchronize()
DispatchQueue.main.async {
sw.isOn = false
}
} else {
// 校驗(yàn)失敗
/// 取消:Canceled by user.
/// 未開啟或設(shè)備不支持:No fingers are enrolled with Touch ID.
// 多次校驗(yàn)失敗? ? 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 {
// 提示校驗(yàn)失敗
message = "指紋不匹配"
}else if desc?.contains("Biometry is") == true {
// 多次校驗(yàn)失敗店乐,彈出用戶輸入密碼解鎖
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "請(qǐng)輸入解鎖密碼", reply: { (success, error) in
if success == true {
// 密碼校驗(yàn)成功
debugPrint("密碼校驗(yàn)成功")
self.switchIsOff(sw: sw)
} else {
// 密碼校驗(yàn)失敗
debugPrint("密碼校驗(yàn)失敗")
}
})
}else {
message = "指紋關(guān)閉失敗"
}
DispatchQueue.main.async {
sw.isOn = true
}
}
if message.characters.count > 0 {
DispatchQueue.main.async {
SVProgressHUD.showInfo(withStatus: message)
SVProgressHUD.dismiss(withDelay: 1)
}
}
debugPrint(message)
})
}
到此我的界面指紋開啟與關(guān)閉可以自由切換 ,下面根據(jù)“我的”界面的設(shè)置完成登錄界面是否展示使用指紋登錄
(1)在viewWillAppear通過指紋UserDefaults取出指紋開關(guān)狀態(tài)呻袭,從而設(shè)置開啟指紋登錄按鈕是否顯示
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鍵驗(yàn)證已有的手機(jī)指紋", reply: { [weak self] (success, authenticationError) in
if success == true {
// 校驗(yàn)成功
self?.autoLogin()
} else {
// 提示
// 校驗(yàn)失敗
/// 取消:Canceled by user.
/// 未開啟或設(shè)備不支持:No fingers are enrolled with Touch ID.
// 三次校驗(yàn)失斦0恕:Application retry limit exceeded
// 多次校驗(yàn)失敗:"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 {
// 多次校驗(yàn)失敗左电,彈出用戶輸入密碼解鎖
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "請(qǐng)輸入解鎖密碼", reply: { (success, error) in
if success == true {
// 密碼校驗(yàn)成功
debugPrint("密碼校驗(yàn)成功")
self?.startFinger()
} else {
// 密碼校驗(yàn)失敗
debugPrint("密碼校驗(yàn)失敗")
}
})
} else if desc?.contains("retry limit exceeded")? == true {
// 提示校驗(yàn)失敗
message = "指紋不匹配"
}
}
if message.characters.count > 0 {
DispatchQueue.main.async {
SVProgressHUD.showInfo(withStatus: message)
SVProgressHUD.dismiss(withDelay: 1)
}
}
})
}
注意:在我的界面從本地取出開關(guān)狀態(tài)的時(shí)候swift與oc 有個(gè)明顯的區(qū)別廉侧,let isOn = UserDefaults.standard.object(forKey: kUseTouchID) as? Bool ? ? ? swift在轉(zhuǎn)換類型前得到的是一個(gè) AnyObject此時(shí)我們理所當(dāng)然轉(zhuǎn)換為bool類型從而進(jìn)行判斷,而oc返回值已為bool類型券腔,但是我們?nèi)詰?yīng)用boolvalue進(jìn)行轉(zhuǎn)化,因?yàn)閛c中未加boolvalue前 我們得到的bool值是通過NSUserDefaults通過key在本地的取值拘泞,如果有值纷纫,則返回yes,如果無值陪腌,則返回no,這不是開關(guān)真實(shí)的狀態(tài)辱魁,所以一定要加boolvalue進(jìn)行強(qiáng)轉(zhuǎn)!
let lineView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: ScreenWidth, height: lineViewHeight))