iOS 以编程方式取消 TouchID 身份验证对话框

iOS cancel TouchID authentication dialog programmatically

是否可以在 LAContext.evaluatePolicy 调用后以编程方式取消 TouchID 警报对话框?如果是:如何?

并非每个 API Apple 发布的内容都会进入 developer.apple.com 上的文档(或 Xcode 的文档查看器中)。 API 差异列表 public APIs,所以你看到的任何东西都在 header 文件(参见 LocalAuthentication/LAContext.h)和 Swift 界面中由那些 header 生成。 header 中的任何内容都是 public API,因此您可以随意调用它。

有时(但不总是)未记录的 API 有体面的 header 评论解释如何使用它们...谢天谢地 LAContext.invalidate() 是其中之一:

/// Invalidates the context.
///
/// @discussion The context is invalidated automatically when it is (auto)released. This method
///             allows invalidating it manually while it is still in scope.
///
///             Invalidation terminates any existing policy evaluation and the respective call will
///             fail with LAErrorAppCancel. After the context has been invalidated, it can not be
///             used for policy evaluation and an attempt to do so will fail with LAErrorInvalidContext.
///
///             Invalidating a context that has been already invalidated has no effect.
@available(iOS 9.0, *)
public func invalidate()

的确,当 Touch ID 警报可见时调用 invalidate() 似乎应该将其关闭。 (我自己没试过。)


iOS 11 更新: 请注意,在使用 Face ID 而不是 Touch ID 的设备上,alert/HUD-like UI 出现在您call LAContext.evaluatePolicy 不需要或不允许交互,并在成功验证后自动关闭。理论上,invalidate 调用仍然会关闭它(或者后续 actually-interactive 如果 Face ID 无法识别用户则出现的警告)。

但是假设在所有可能的设备和身份验证方法上您总是有足够的时间在请求后取消 LAContext 身份验证可能并不明智。

在我的例子中,我发现了为什么它不起作用,因为我尝试使 () 无效的 LAContext 实例与我调用 evaluatePolicy() 的实例不同。

因此您需要确保所有 ViewController 共享同一个实例。 swift 4

public class MyBiometryUtility: NSObject {
static private var sharedBiometry: MyBiometryUtility? = nil
var context: LAContext = LAContext()
@objc public static func sharedInstance() -> MyBiometryUtility{
        if let sharedBiometry = sharedBiometry {
            return sharedBiometry;
        } else{
            sharedBiometry = MyBiometryUtility()
            return sharedBiometry!
        }
    }
public func tryBiometryAuth() { ... }
public func closeBiometryAuth() {... }

在SomeViewController.swift

func buttonTapped(sender: Any){
    // show dialog.
    MyBiometryUtility.sharedInstance().tryBiometryAuth()
}
func timerCountDown(){
    // close dialog.
    if tooLong() {
        MyBiometryUtility.sharedInstance().closeBiometryAuth()
    }
}