FaceID должен вернуться к паролю, но не - PullRequest
0 голосов
/ 18 апреля 2019

Я унаследовал кодовую базу со следующим классом, обеспечивающим поддержку Face / Touch ID.

Ожидаемое поведение: при успешном входе в систему через Face / Touch ID пользователь входит в систему. Это работает.

Однако, если пользователь не сможет идентифицировать лицо и решит ввести свой пароль, он будет отключен после вызова обработчика завершения. Я считаю, что выбор использования пароля вызывает

else {
 self.authState = .unauthenticated
 completion(.unauthenticated)
}

Как я могу вместо этого вызвать запрос пароля? Должен ли я создать вторую политику, используя LAPolicy.deviceOwnerAuthentication и оценить ее вместо этого?

import LocalAuthentication

public enum AuthenticationState {
    case unknown
    case authenticated
    case unauthenticated

    public func isAuthenticated() -> Bool {
        return self == .authenticated
    }
}

public protocol TouchIDAuthenticatorType {
    var authState: AuthenticationState { get }
    func authenticate(reason: String, completion: @escaping (AuthenticationState) -> Void) -> Void
    func removeAuthentication() -> Void
}

public protocol LAContextType: class {
    func canEvaluatePolicy(_ policy: LAPolicy, error: NSErrorPointer) -> Bool
    func evaluatePolicy(_ policy: LAPolicy, localizedReason: String, reply: @escaping (Bool, Error?) -> Void)
}

public class TouchIDAuthenticator: TouchIDAuthenticatorType {
    public var authState: AuthenticationState = .unknown

    private var context: LAContextType
    private var policy = LAPolicy.deviceOwnerAuthenticationWithBiometrics

    public init(context: LAContextType = LAContext()) {
        self.context = context
    }

    public func authenticate(reason: String, completion: @escaping (AuthenticationState) -> Void) -> Void {
        var error: NSError?

        if context.canEvaluatePolicy(policy, error: &error) {
            context.evaluatePolicy(policy, localizedReason: reason) { (success, error) in
                DispatchQueue.main.async {
                    if success {
                        self.authState = .authenticated
                        completion(.authenticated)
                    } else {
                        self.authState = .unauthenticated
                        completion(.unauthenticated)
                    }
                }
            }
        } else {
            authState = .authenticated
            completion(.authenticated)
        }
    }

    public func removeAuthentication() -> Void {
        authState = .unknown
        context = LAContext() // reset the context
    }
}

extension LAContext: LAContextType { }

Я должен отметить, что на симуляторе это работает должным образом, но на устройстве это не так, и я вышел из системы.

...