Face ID prompt delay when the app coming from background to foreground (SwiftUI)

1.4k views Asked by At

I'm trying to lock my app when the app goes to background and the user can unlock the app when the app is in the foreground using biometric (FaceID/TouchID) authentication.

Here's a simple, reproducible example of my code:

import LocalAuthentication
import SwiftUI

struct ContentView: View {
    @State var isUnlocked = false
    
    var body: some View {
        if isUnlocked { 

            // if the app is unlocked, app shows the text "Unlocked"
            Text("Unlocked")
                .font(.title)

                // app gets locked when the app goes to background
                .onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
                    self.isUnlocked = false
                    print("locked the app")
                }

        } else { 

            // if the app is locked, app shows the text "Locked" and app should show prompt FaceID/TouchID prompt
            Text("LOCKED")
                .font(.title)

                // FaceID prompt shows when the app opens (from Non-running state)
                .onAppear(perform: authenticate)

                // FaceID prompt shows when the app coming from background to foreground
                .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
                    authenticate()
                    print("back inside the app")
                }
        }
        
    }
    
    // I use this to prompt the biometric authentication
    func authenticate() {
        let context = LAContext()
        var error: NSError?
        
        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            let reason = "We need to unlock your data"
            
            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
                DispatchQueue.main.async {
                    if success {
                        // app gets unlocked if biometrix authentication succeeded
                        self.isUnlocked = true
                    } else {
                        // authentication failed
                    }
                }
            }
        } else {
            // no biometrics
        }
    }

}

When the user opens the app (from non-running state), FaceID prompt shows instantly without any delay. BUT when the app comes from background to foreground, FaceID prompt takes around 5 seconds to show up. I use the same function authenticate() to prompt the biometric authentication and Xcode console prints "back inside the app" instantly when the app comes from background to foreground.
So what causes that FaceID delay?

Please help me. Thanks.

0

There are 0 answers