【问题标题】:Touch ID causing app to become non-responsiveTouch ID 导致应用程序无响应
【发布时间】:2014-12-15 06:58:27
【问题描述】:

我在我的应用程序中添加了 ios-8 的新 touchID API。 它通常按预期工作,但是当我的手指已经在主页按钮上时进入应用程序 - 调用 API 的成功回调但弹出窗口仍然出现在屏幕上。按下 CANCEL 后 UI 变得无响应。

【问题讨论】:

    标签: ios ios8 touch-id


    【解决方案1】:

    我也遇到了同样的问题,解决方法是使用高优先级队列调用Touch ID API,还有延迟:

    // Touch ID must be called with a high priority queue, otherwise it might fail.
    // Also, a dispatch_after is required, otherwise we might receive "Pending UI mechanism already set."
    dispatch_queue_t highPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.75 * NSEC_PER_SEC), highPriorityQueue, ^{
      LAContext *context = [[LAContext alloc] init];
      NSError *error = nil;
    
      // Check if device supports TouchID
      if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
          // TouchID supported, show it to user
          [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                  localizedReason:@"Unlock Using Touch ID"
                            reply:^(BOOL success, NSError *error) {
                                if (success) {
                                    // This action has to be on main thread and must be synchronous
                                    dispatch_async(dispatch_get_main_queue(), ^{
                                        ...
                                    });
                                }
                                else if (error) {
                                    ...
                                }
                            }];
      }
    });
    

    在测试我们的应用时,我们发现 750 毫秒的延迟是最佳的,但您的里程可能会有所不同。

    更新(2015 年 3 月 10 日): 一些 iOS 开发者,例如 1Password,are reporting,表示 iOS 8.2 终于修复了这个问题。

    【讨论】:

    • 使用 iOS 8.2 也有同样的问题。看起来问题还没有完全解决。
    • @JOM 它似乎在 iOS 8.2 上对我有用,没有 750 毫秒的延迟,但调用它时仍然需要高优先级队列。
    • 当前在 performSelector 循环中检查 UIApplicationStateActive,但必须检查那个高优先级循环。感谢您的提示!
    【解决方案2】:

    这个公认的答案没有解决问题的根本原因:调用 evaluatePolicy() 两次,第二次是在第一次调用正在进行时。因此,当前的解决方案有时只能靠运气起作用,因为一切都取决于时间。

    解决该问题的蛮力、直接的方法是一个简单的布尔标志,以防止在第一次调用完成之前发生后续调用。

    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    if ( NSClassFromString(@"LAContext") && ! delegate.touchIDInProgress ) {
        delegate.touchIDInProgress = YES;
        LAContext *localAuthenticationContext = [[LAContext alloc] init];
        __autoreleasing NSError *authenticationError;
        if ([localAuthenticationContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authenticationError]) {
            [localAuthenticationContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:kTouchIDReason reply:^(BOOL success, NSError *error) {
                delegate.touchIDInProgress = NO;
                if (success) {
                    ...
                } else {
                    ...
                }
            }];
        }
    

    【讨论】:

    • 我刚刚在我们的应用程序中实现了您的解决方案,但它不起作用 - 我们遇到了 @HeTzi 遇到的同样问题。
    • 有趣。建议的解决方案对我不起作用,并且由于临时的时间考虑,不能成为一个合适的解决方案。我有兴趣查看您的代码,特别是,如果您对代码进行检测以验证代码是否被连续调用......在我的情况下,它显然是。谢谢。
    • 另外,也许我们对“无响应”的定义不同。在我的情况下,调用 evaluatePolicy() 两次会使 Touch ID 视图打开(屏幕变暗),没有任何效果,您会看到这是日志: touchID failed Error Domain=com.apple.LocalAuthentication Code=-1000 "Pending UI mechanism already set 。” UserInfo=0x17446e900 {NSLocalizedDescription=Pending UI 机制已设置。} 添加 BOOL 检查以防止这种情况发生确实可以解决问题。
    • 所以现在请注意最近关于应用程序状态的答案......我们将很快得到“待定 UI 机制已设置”问题的适当解决方案:) 但重要的是要注意接受使用计时器延迟的答案不可能是正确的,只能偶然发生。
    【解决方案3】:

    虽然使用延迟可以潜在地解决问题,但它掩盖了根本原因。您需要确保仅当应用程序状态为活动时才显示 Touch ID 对话框。如果您在启动过程中立即显示它(这意味着应用程序在技术上仍处于非活动状态),则可能会出现这些类型的显示问题。这没有记录在案,我很难找到这一点。提供延迟似乎可以解决它,因为那时您的应用程序处于活动状态,但这并不能保证。

    为确保它在应用程序处于活动状态时运行,您可以检查当前应用程序状态,并立即运行它,或者在我们收到 applicationDidBecomeActive 通知时运行它。请参阅下面的示例:

    - (void)setup
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationDidBecomeActive:)
                                                     name:UIApplicationDidBecomeActiveNotification
                                                   object:nil];
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
    
        // We need to be in an active state for Touch ID to play nice
        // If we're not, defer the presentation until we are
        if([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
        {
            [self presentTouchID];
        }
        else
        {
            __weak __typeof(self) wSelf = self;
            _onActiveBlock = ^{
                [wSelf presentTouchID];
            };
        }
    }
    
    -(void)applicationDidBecomeActive:(NSNotification *)notif
    {
        if(_onActiveBlock)
        {
            _onActiveBlock();
            _onActiveBlock = nil;
        }
    }
    
    - (void)presentTouchID
    {
        _context = [[LAContext alloc] init];
        _context.localizedFallbackTitle = _fallbackTitle;
        [_context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                 localizedReason:_reason
                           reply: ^(BOOL success, NSError *authenticationError)
         {
             // Handle response here
         }];
    }
    

    【讨论】:

    • 这比接受的答案要好得多,因为此解决方案不会引入任何烦人的延迟。很好的收获,谢谢!但我仍然认为这个问题应该由 Apple 在 SDK 中解决,因为显然几乎每个应用程序都会遇到这个问题。
    • 我使用了类似的解决方案,关键是检查/等待 UIApplicationStateActive。非常感谢!
    【解决方案4】:

    我开始收到“已设置待定 UI 机制”。也提到了错误,所以我决定看看其他应用程序是否受到影响。我为 Touch ID 设置了 Dropbox 和 Mint。果然,Touch ID 也对他们不起作用,他们只能使用密码。

    我重新启动了我的手机,它又开始工作了,所以 Touch ID 似乎会出错并停止工作。我在 iOS 8.2 顺便说一句。

    我猜想处理这种情况的正确方法就像那些应用程序一样,然后回退到密码/密码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多