I have a simple requirement, if the user allows Face ID , open the app after Face ID is successful..
So my app has Face ID enabled
Now I launch the app and each time I do so , the Face ID is checked
I update a published value to true and I can see , that it is updated as well. but some how the check loops...
However the problem is a loop , this process , just keeps repeating, I know I am making a logical error here, can some one please have a look at my code and suggest a few work around, thanks
I call the authentic from my @main
import SwiftUI
import LocalAuthentication
import NotificationCenter
@main
struct CollectionApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject var dataController = DataController()
var body: some Scene {
WindowGroup {
if dataController.isLocked {
ContentView()
.environment(\.managedObjectContext, dataController.container.viewContext)
}
else {
Text("Not authenticated")
}
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(self.updateView), name: UIApplication.didBecomeActiveNotification, object: nil)
return true
}
@objc func updateView() {
print(DataController.shared.isLocked)
authenticate()
}
func authenticate() {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "we need to implement face id"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in
if success {
DataController.shared.isLocked = true. <—— published value
} else {
// showAppSettings()
print("Not done yet")
}
}
} else {
//no biometrics
}
}
}
CodePudding user response:
Replace
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(self.updateView), name: UIApplication.didBecomeActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.willResignActive), name: UIApplication.willResignActiveNotification, object: nil)
return true
}
@objc func willResignActive() {
DataController.shared.isLocked = false
}
@objc func updateView() {
if !DataController.shared.isLocked {
authenticate()
}
}
and replace
@StateObject var dataController = DataController.shared
and replace
DispatchQueue.main.async {
DataController.shared.isLocked = true
}