在 SwiftUI 中,可以通过集成 LocalAuthentication 框架来使用 Touch ID 和 Face ID。这些功能被统称为 生物识别认证,适用于设备锁定、应用保护、数据安全等场景。
实现步骤
1、导入框架
引入 LocalAuthentication 框架以访问生物识别认证功能。
import LocalAuthentication
2、创建认证逻辑
使用 LAContext 来执行生物识别认证。
3. 集成到 SwiftUI 界面
将认证逻辑绑定到 SwiftUI 的视图中,通过按钮触发或其他条件自动执行。
完整代码示例
以下是一个使用 Touch ID 或 Face ID 的示例应用:
import SwiftUI
import LocalAuthentication
struct ContentView: View {
@State private var isAuthenticated = false
@State private var errorMessage = ""
var body: some View {
VStack(spacing: 20) {
if isAuthenticated {
Text("Welcome! 🎉")
.font(.largeTitle)
.foregroundColor(.green)
} else {
Text("Please authenticate")
.font(.title)
.foregroundColor(.red)
Button(action: authenticate) {
Label("Unlock with Biometrics", systemImage: "faceid")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.clipShape(Capsule())
}
if !errorMessage.isEmpty {
Text("Error: \(errorMessage)")
.foregroundColor(.red)
.font(.footnote)
}
}
}
.padding()
}
func authenticate() {
let context = LAContext()
var error: NSError?
// 检查设备是否支持生物识别
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Authenticate to access your account"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
if success {
isAuthenticated = true
errorMessage = ""
} else {
isAuthenticated = false
errorMessage = authenticationError?.localizedDescription ?? "Unknown error"
}
}
}
} else {
// 设备不支持生物识别
DispatchQueue.main.async {
errorMessage = error?.localizedDescription ?? "Biometric authentication is not available"
}
}
}
}
#Preview {
ContentView()
}
代码功能
1、检查当前设备是否支持生物识别验证。
2、如果支持,则调用生物识别功能进行身份验证。
3、根据验证结果(成功或失败),执行不同的逻辑。
4、如果设备不支持生物识别,则返回错误信息。
代码解析
这段 Swift 代码实现了设备生物识别验证(如 Face ID 或 Touch ID)的逻辑,主要是用来检查设备是否支持生物识别验证,并根据用户的验证结果执行相应操作。以下是详细解析:
1、创建生物识别上下文
let context = LAContext()
var error: NSError?
LAContext 是 LocalAuthentication 框架中的类,用来管理身份验证的上下文环境。
error 是一个可选的 NSError,用于存储设备不支持生物识别验证时的错误信息。
2、检查设备是否支持生物识别
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
canEvaluatePolicy 是用来检查设备是否支持特定的身份验证策略。
参数 .deviceOwnerAuthenticationWithBiometrics 表示使用生物识别(如 Face ID 或 Touch ID)验证用户身份。
如果设备支持生物识别功能,canEvaluatePolicy 返回 true;否则返回 false 并将错误信息存储在 error 中。
3、调用生物识别验证
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
if success {
isAuthenticated = true
errorMessage = ""
} else {
isAuthenticated = false
errorMessage = authenticationError?.localizedDescription ?? "Unknown error"
}
}
}
1)evaluatePolicy 方法:
发起生物识别验证,弹出系统提供的身份验证界面。
参数:
.deviceOwnerAuthenticationWithBiometrics:生物识别验证策略。
localizedReason:向用户解释为什么需要验证(会显示在系统弹出的验证对话框中)。
2)闭包返回两个参数:
success:一个布尔值,表示验证是否成功。
authenticationError:验证失败时的错误信息。
3)DispatchQueue.main.async:
确保 UI 更新在主线程中完成。
4)成功时的逻辑:
isAuthenticated = true
errorMessage = ""
5)失败时的逻辑:
isAuthenticated = false
errorMessage = authenticationError?.localizedDescription ?? "Unknown error"
4、处理设备不支持生物识别的情况
DispatchQueue.main.async {
errorMessage = error?.localizedDescription ?? "Biometric authentication is not available"
}
如果设备不支持生物识别,进入 else 块。
更新 errorMessage,告知用户设备不支持生物识别验证,并提供错误的具体描述。
生物识别认证报错
在首次识别时,可能存在无法识别认证的情况,Xcode报错输出:
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSFaceIDUsageDescription key with a string value explaining to the user how the app uses this data.
这是因为应用没有在Info.plist文件中声明使用Face ID的权限描述,因此iOS系统拒绝了对生物识别功能的访问。这是一个必要的步骤,否则应用会崩溃。
解决步骤
1、找到项目的Info.plist文件。
2、在Info.plist文件中新增:
Privacy - Face ID Usage Description
我们需要使用 Face ID 来解锁您的数据。 // Value值
Privacy – Face ID Usage Description 是一个键(Key),它代表你的应用请求使用 Face ID 功能时显示的权限描述。
右侧的 Value 列是键的对应值,也就是应用向用户解释为什么需要使用 Face ID 的具体内容。
3、重新启动应用,问题得到解决。
用户控制生物识别认证
1、添加控制生物识别的布尔值
@AppStorage("isBiometricEnabled") private var isBiometricEnabled = false
2、给生物识别添加判断,检查是否启用识别变量
// 检查用户是否启用了生物识别验证
guard isBiometricEnabled else {
print("Biometric authentication is disabled by the user.")
return
}
3、添加生物识别控制按钮
Toggle("Enable Biometric Authentication", isOn: $isBiometricEnabled)
.padding()
修改后,实现用户通过按钮控制生物识别认证功能。
实现效果
完整代码示例
import SwiftUI
import LocalAuthentication
struct ContentView: View {
@State private var isUnlocked = false
@AppStorage("isBiometricEnabled") private var isBiometricEnabled = false
func authenticate() {
let context = LAContext()
var error: NSError?
// 检查用户是否启用了生物识别验证
guard isBiometricEnabled else {
print("Biometric authentication is disabled by the user.")
return
}
// 检查是否可以使用生物识别
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "We need to unlock your data."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
if success {
self.isUnlocked = true
} else {
print("Authentication failed: \(authenticationError?.localizedDescription ?? "Unknown error")")
}
}
}
} else {
print("Biometric authentication is not available: \(error?.localizedDescription ?? "Unknown error")")
}
}
var body: some View {
NavigationView {
VStack {
if isUnlocked {
Text("Unlocked")
.font(.largeTitle)
.foregroundColor(.green)
} else {
Text("Locked")
.font(.largeTitle)
.foregroundColor(.red)
}
Toggle("Enable Biometric Authentication", isOn: $isBiometricEnabled)
.padding()
Button("Authenticate") {
authenticate()
}
.padding()
}
.navigationTitle("Biometric Settings")
}
}
}
#Preview {
ContentView()
}
生物识别验证的备选方案
如果设备不支持生物识别或者用户拒绝验证,可以提供密码作为备选方案:
context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error)
deviceOwnerAuthentication 的含义
.deviceOwnerAuthentication 是一种更通用的身份验证策略。
它不仅支持生物识别验证(如 Face ID 或 Touch ID),还支持设备密码(PIN、图案或设备解锁密码)作为备选方案。
如果设备不支持生物识别,或者用户多次失败,系统会自动回退到设备密码验证。
如何使用
可以将 .deviceOwnerAuthentication 添加到现有代码中,作为生物识别验证的备选方案。例如:
func authenticate() {
let context = LAContext()
var error: NSError?
// 检查设备是否支持生物识别或设备密码验证
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
let reason = "Authenticate to access your account"
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
if success {
isAuthenticated = true
errorMessage = ""
} else {
isAuthenticated = false
errorMessage = authenticationError?.localizedDescription ?? "Unknown error"
}
}
}
} else {
// 设备不支持生物识别或密码验证
DispatchQueue.main.async {
errorMessage = error?.localizedDescription ?? "Authentication is not available"
}
}
}
1、替换 deviceOwnerAuthenticationWithBiometrics
将策略从 .deviceOwnerAuthenticationWithBiometrics 替换为 .deviceOwnerAuthentication:
如果用户设备支持生物识别,会优先使用生物识别。
如果用户多次失败,或者设备不支持生物识别,系统会回退到密码验证。
2、用户体验改进
用户在生物识别验证失败后,可以直接输入密码继续验证,而无需额外处理逻辑。
即使用户的设备完全不支持生物识别(例如旧设备),仍然可以通过密码验证。
注意事项
1、Face ID/Touch ID 描述不再适用
在弹出的验证对话框中,localizedReason 会展示给用户。如果用户用的是密码验证,这个描述可能需要更通用的描述,例如:
进行身份验证以安全访问您的帐户
2、错误处理
在用户取消或失败后,可以检查 authenticationError,并根据错误类型提供具体提示。例如:
LAError.userCancel:用户取消验证。
LAError.authenticationFailed:身份验证失败。
3、回退逻辑
如果用户设备完全不支持 .deviceOwnerAuthentication(非常少见),可以提示用户使用另一种方法访问应用(例如注册账号或输入固定密码)。
参考资料
Using Touch ID and Face ID with SwiftUI:https://www.hackingwithswift.com/books/ios-swiftui/using-touch-id-and-face-id-with-swiftui