------------------------- | Biometric Authentication | |-------------------------| | | | [ Authenticate ] | | | | Status: | | | -------------------------
Biometric authentication (Face ID, Touch ID) in iOS Swift - Mini App: Build & Ship
import SwiftUI import LocalAuthentication struct BiometricAuthScreen: View { @State private var statusMessage = "" var body: some View { VStack(spacing: 20) { // TODO: Add Authenticate button here // TODO: Show statusMessage text here } .padding() } } struct BiometricAuthScreen_Previews: PreviewProvider { static var previews: some View { BiometricAuthScreen() } }
import SwiftUI import LocalAuthentication struct BiometricAuthScreen: View { @State private var statusMessage = "" var body: some View { VStack(spacing: 20) { Button("Authenticate") { authenticateUser() } .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(8) Text(statusMessage) .foregroundColor(.gray) .multilineTextAlignment(.center) .padding(.horizontal) } .padding() } func authenticateUser() { let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { let reason = "Please authenticate to continue." context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in DispatchQueue.main.async { if success { statusMessage = "Authentication succeeded" } else { if let error = authenticationError { statusMessage = error.localizedDescription } else { statusMessage = "Authentication failed" } } } } } else { DispatchQueue.main.async { if let error = error { statusMessage = error.localizedDescription } else { statusMessage = "Biometric authentication not available or not enrolled" } } } } } struct BiometricAuthScreen_Previews: PreviewProvider { static var previews: some View { BiometricAuthScreen() } }
This solution uses SwiftUI to create a simple screen with a button labeled Authenticate. When the user taps the button, the authenticateUser() function runs.
Inside authenticateUser(), we create an LAContext object to check if biometric authentication is available and enrolled on the device.
If biometrics are available, we call evaluatePolicy to prompt the user for Face ID or Touch ID. The result is handled asynchronously, updating the statusMessage state to show success or failure.
If authentication fails, we show the error message if available, otherwise a generic failure message.
If biometrics are not available or not enrolled, we update the status message accordingly, showing the error description if available.
The UI updates automatically because statusMessage is a @State variable, and the text below the button shows the current status.
------------------------- | Biometric Authentication | |-------------------------| | | | [ Authenticate ] | | | | Status: | | Authentication succeeded | -------------------------
Practice
Solution
Step 1: Understand biometric authentication purpose
Biometric authentication is designed to verify the user's identity securely using Face ID or Touch ID.Step 2: Compare options with purpose
Only To securely verify the user's identity without typing a password describes secure identity verification without passwords, which is the main goal.Final Answer:
To securely verify the user's identity without typing a password -> Option CQuick Check:
Biometric authentication = Secure identity check [OK]
- Thinking biometrics speed up app loading
- Confusing biometric use with UI changes
- Assuming biometrics send notifications
Solution
Step 1: Identify correct method to check biometric availability
The method canEvaluatePolicy with .deviceOwnerAuthenticationWithBiometrics checks if biometrics are available.Step 2: Verify code syntax and usage
let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { // proceed } uses canEvaluatePolicy with correct policy and proper &error parameter, matching Apple's guidelines.Final Answer:
let context = LAContext()\nvar error: NSError?\nif context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {\n // proceed\n} -> Option BQuick Check:
Check biometrics availability = canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics) [OK]
- Using evaluatePolicy instead of canEvaluatePolicy for availability
- Using wrong policy like .deviceOwnerAuthentication
- Calling non-existent methods like canAuthenticate
let context = LAContext()
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Access needed") { success, error in
if success {
print("Authentication succeeded")
} else {
print("Authentication failed")
}
}Solution
Step 1: Understand evaluatePolicy callback behavior
The closure receives a success boolean indicating if authentication passed.Step 2: Check the if condition for success
If success is true, it prints "Authentication succeeded"; otherwise, it prints failure.Final Answer:
Authentication succeeded -> Option AQuick Check:
Success true prints "Authentication succeeded" [OK]
- Confusing success and failure branches
- Assuming no output from async closure
- Thinking code has syntax errors
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: error) {
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Login") { success, error in
if success {
print("Access granted")
}
}
}Solution
Step 1: Check error parameter usage in canEvaluatePolicy
The error parameter must be passed as an inout pointer using &error to capture errors.Step 2: Verify other code parts
evaluatePolicy is correctly called after canEvaluatePolicy, localizedReason is provided, and LAContext can be a let constant.Final Answer:
The error parameter should be passed as &error to be mutable -> Option AQuick Check:
Error param must be &error for canEvaluatePolicy [OK]
- Passing error without & causing no error info
- Calling evaluatePolicy before checking availability
- Missing localizedReason string
- Misunderstanding let vs var for LAContext
Solution
Step 1: Understand fallback requirement
The app should try biometrics first, then fallback to device passcode if biometrics fail or are unavailable.Step 2: Analyze code options for fallback logic
let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) { context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Authenticate") { success, error in if success { print("Authentication success") } else { print("Authentication failed") } } } uses .deviceOwnerAuthentication policy which automatically prefers biometrics (Face ID/Touch ID) and falls back to passcode if unavailable or fails. It also properly checks availability first per Apple's guidelines.Final Answer:
let context = LAContext()\nvar error: NSError?\nif context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {\n context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: \"Authenticate\") { success, error in\n if success {\n print(\"Authentication success\")\n } else {\n print(\"Authentication failed\")\n }\n }\n} -> Option DQuick Check:
.deviceOwnerAuthentication policy = biometric fallback to passcode [OK]
- Using biometrics-only policy without fallback (Options A, B)
- Direct evaluation without availability check
- Syntax error with error: nil and incomplete fallback (Option D)
Ready to prove it?
Pass the test and this pattern moves unknown
