Skip to content

Instantly share code, notes, and snippets.

@ArtCC
Last active April 23, 2025 11:28
Show Gist options
  • Select an option

  • Save ArtCC/4026fb66417d8d9475a8724b4fb4fe9e to your computer and use it in GitHub Desktop.

Select an option

Save ArtCC/4026fb66417d8d9475a8724b4fb4fe9e to your computer and use it in GitHub Desktop.
BiometricManager (Swift 6 compatibility)
import LocalAuthentication
@MainActor
protocol BiometricManagerProtocol: Sendable {
func biometricType() -> BiometricManager.BiometricType
func isBiometricAvailable() -> Bool
func authenticate(reason: String?) async throws -> Bool
func updateLoginReason(_ newReason: String)
}
@MainActor
final class BiometricManager: BiometricManagerProtocol {
// MARK: - Properties
enum BiometricType: String, Sendable, CaseIterable {
case faceID
case opticID
case touchID
case unknown
}
static let shared = BiometricManager()
private var loginReason: String
// MARK: - Init
private init() {
self.loginReason = "Authenticate to access"
}
// MARK: - Public functions
func biometricType() -> BiometricType {
let context = LAContext()
var error: NSError?
guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
return .unknown
}
if #available(iOS 11.0, *) {
switch context.biometryType {
case .none:
return .unknown
case .touchID:
return .touchID
case .faceID:
return .faceID
case .opticID:
return .opticID
@unknown default:
return .unknown
}
} else {
return .touchID
}
}
func isBiometricAvailable() -> Bool {
let context = LAContext()
var error: NSError?
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
}
func authenticate(reason: String?) async throws -> Bool {
let context = LAContext()
let authReason = reason ?? loginReason
let policy: LAPolicy = .deviceOwnerAuthentication
return try await withCheckedThrowingContinuation { [context] continuation in
context.evaluatePolicy(policy, localizedReason: authReason) { success, error in
continuation.resume(with: Result {
if success {
return true
} else if let error {
throw error
} else {
throw LAError(.appCancel)
}
})
}
}
}
func updateLoginReason(_ newReason: String) {
loginReason = newReason
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment