6774d76146
- AppLockService.biometryKind lee LAContext.biometryType; textos e icono del bloqueo y de la privacidad de saldos ya no asumen Face ID (Duo puede llevar Touch ID). Nuevas claves biometric_* en los 7 idiomas. - Entrada 1.7.0 en el catálogo What's New (Duo, inspector, biometría) con strings en los 7 idiomas. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F1u4K16xy7eQVtgsYNZ9Vn
68 lines
2.2 KiB
Swift
68 lines
2.2 KiB
Swift
import Foundation
|
|
import LocalAuthentication
|
|
|
|
/// Biometric hardware available on this device. Never assume Face ID: iPad and
|
|
/// iPhone Duo can ship with Touch ID, Vision Pro with Optic ID.
|
|
enum BiometryKind {
|
|
case faceID
|
|
case touchID
|
|
case opticID
|
|
case none
|
|
|
|
/// Marketing name shown in UI ("Face ID", "Touch ID", "Optic ID"). Falls back
|
|
/// to a generic label when no biometry is available (e.g. not enrolled).
|
|
var displayName: String {
|
|
switch self {
|
|
case .faceID: return "Face ID"
|
|
case .touchID: return "Touch ID"
|
|
case .opticID: return "Optic ID"
|
|
case .none: return String(localized: "biometric_generic_name")
|
|
}
|
|
}
|
|
|
|
/// SF Symbol matching the hardware.
|
|
var systemImage: String {
|
|
switch self {
|
|
case .faceID: return "faceid"
|
|
case .touchID: return "touchid"
|
|
case .opticID: return "opticid"
|
|
case .none: return "lock.shield"
|
|
}
|
|
}
|
|
}
|
|
|
|
enum AppLockService {
|
|
static func canUseBiometrics() -> Bool {
|
|
let context = LAContext()
|
|
var error: NSError?
|
|
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
|
|
}
|
|
|
|
/// The biometry type reported by the system. `biometryType` is only populated
|
|
/// after `canEvaluatePolicy` runs, and stays set even when not enrolled.
|
|
static var biometryKind: BiometryKind {
|
|
let context = LAContext()
|
|
var error: NSError?
|
|
_ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
|
|
switch context.biometryType {
|
|
case .faceID: return .faceID
|
|
case .touchID: return .touchID
|
|
case .opticID: return .opticID
|
|
case .none: return .none
|
|
@unknown default: return .none
|
|
}
|
|
}
|
|
|
|
/// Localized biometry name for user-facing text.
|
|
static var biometryName: String { biometryKind.displayName }
|
|
|
|
static func authenticate(reason: String, completion: @escaping (Bool) -> Void) {
|
|
let context = LAContext()
|
|
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, _ in
|
|
DispatchQueue.main.async {
|
|
completion(success)
|
|
}
|
|
}
|
|
}
|
|
}
|