The vast majority of Apple’s devices come with biometric authentication as standard, which means they use fingerprint, facial, and even iris recognition to unlock. This functionality is available to us too, which means we can make sure that sensitive data can only be read when unlocked by a valid user.
This is another Objective-C API, but it’s only a little bit unpleasant to use with SwiftUI, which is better than we’ve had with some other frameworks we’ve looked at so far.
Before we write any code, you need to add a new key to your project options, explaining to the user why you want access to Face ID. For reasons known only to Apple, we pass the Touch ID request reason in code, and the Face ID request reason in project options.
So, select your current target, go to the Info tab, right-click on an existing key, then choose Add Row. Scroll through the list of keys until you find “Privacy - Face ID Usage Description” and give it the value “We need to unlock your data.”
Now head back to ContentView.swift, and add this import near the top of the file:
import LocalAuthentication
And with that, we’re all set to write some biometrics code.
I mentioned earlier this was “only a little bit unpleasant”, and here’s where it comes in: Swift developers use the Error
protocol for representing errors that occur at runtime, but Objective-C uses a special class called NSError
. We need to be able to pass that into the function and have it changed inside the function rather than returning a new value – although this was the standard in Objective-C, it’s quite an alien way of working in Swift so we need to mark this behavior specially by using &
.
We’re going to write an authenticate()
method that isolates all the biometric functionality in a single place. To make that happen requires four steps:
LAContext
, which allows us to query biometric status and perform the authentication check.Please go ahead and add this method to ContentView
:
func authenticate() {
let context = LAContext()
var error: NSError?
// check whether biometric authentication is possible
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
// it's possible, so go ahead and use it
let reason = "We need to unlock your data."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
// authentication has now completed
if success {
// authenticated successfully
} else {
// there was a problem
}
}
} else {
// no biometrics
}
}
That method by itself won’t do anything, because it’s not connected to SwiftUI at all. To fix that we need to add some state we can adjust when authentication is successful, and also an onAppear()
modifier to trigger authentication.
So, first add this property to ContentView
:
@State private var isUnlocked = false
That simple Boolean will store whether the app is showing its protected data or not, so we’ll flip that to true when authentication succeeds. Replace the // authenticated successfully
comment with this:
isUnlocked = true
Finally, we can show the current authentication state and begin the authentication process inside the body
property, like this:
VStack {
if isUnlocked {
Text("Unlocked")
} else {
Text("Locked")
}
}
.onAppear(perform: authenticate)
If you run the app there’s a good chance you just see “Locked” and nothing else. This is because the simulator isn’t opted in to biometrics by default, and we didn’t provide any error messages, so it fails silently.
To take Face ID for a test drive in the simulator, go to the Features menu and choose Face ID > Enrolled, then launch the app again. This time you should see the Face ID prompt appear, and you can trigger successful or failed authentication by going back to the Features menu and choosing Face ID > Matching Face or Non-matching Face.
All being well you should see the Face ID prompt go away, and underneath it will be the “Unlocked” text view – our app has detected the authentication, and is now open to use.
Important: When working with biometric authentication, you should always look for a backup plan that lets users authenticate without biometrics. This usually means adding a screen that prompts for a passcode then providing that as a fallback if biometrics fail, but this is something you need to build yourself.
GO FURTHER, FASTER Unleash your full potential as a Swift developer with the all-new Swift Career Accelerator: the most comprehensive, career-transforming learning resource ever created for iOS development. Whether you’re just starting out, looking to land your first job, or aiming to become a lead developer, this program offers everything you need to level up – from mastering Swift’s latest features to conquering interview questions and building robust portfolios.
Link copied to your pasteboard.