Touch ID entraînant la non-réactivité de l'application

J'ai ajouté la nouvelle API touchID de ios-8 à mon application. Il fonctionne généralement comme prévu, MAIS lors de la saisie de l'application alors que mon doigt est déjà sur le button d'accueil – le callback de succès de l'API est appelé, mais une window contextuelle apparaît toujours à l'écran. après avoir appuyé sur CANCEL UI devient non-réactif.

    J'ai également rencontré le même problème, et la solution consistait à appeler l'appel à l'API Touch ID en utilisant une queue haute priorité, ainsi qu'un timeout:

    // 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:LAPolicyDeviceOwnerAuthenticationWithBiomesortingcs error:&error]) { // TouchID supported, show it to user [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiomesortingcs 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) { ... } }]; } }); 

    Lors du test de notre application, nous avons trouvé un timeout de 750ms pour être optimal, mais votre kilométrage peut varier.

    Mise à jour (03/10/2015): Plusieurs développeurs iOS, comme 1Password par exemple, signalent que iOS 8.2 a finalement résolu ce problème.

    Si l'utilisation d'un timeout peut potentiellement résoudre le problème, elle masque la cause première. Vous devez vous assurer que vous n'affichez que la boîte de dialog Touch ID lorsque l'état de l'application est actif. Si vous l'affichez immédiatement pendant le process de lancement (ce qui signifie que l'application est toujours techniquement dans un état inactif), ces types de problèmes d'affichage peuvent se produire. Ce n'est pas documenté, et je l'ai trouvé à la dure. Fournir un timeout semble le réparer parce que votre application est dans un état actif d'ici là, mais cela n'est pas garanti.

    Pour vous assurer qu'il s'exécute lorsque l'application est active, vous pouvez vérifier l'état actuel de l'application et l'exécuter immédiatement ou lorsque nous recevons la notification applicationDidBecomeActive. Voir ci-dessous pour un exemple:

     - (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:LAPolicyDeviceOwnerAuthenticationWithBiomesortingcs localizedReason:_reason reply: ^(BOOL success, NSError *authenticationError) { // Handle response here }]; } 

    Cette réponse acceptée n'aborde pas la cause sous-jacente du problème: invoquant evaluatePolicy () deux fois, la deuxième fois pendant que le premier appel est en cours. Donc, la solution actuelle ne fonctionne que par chance, car tout dépend du timing.

    La méthode brute-force, simple pour contourner le problème est un simple indicateur boolean pour empêcher les appels subséquents de se produire jusqu'à ce que le premier se termine.

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

    J'ai commencé à get le "mécanisme d'interface user en attente déjà défini." erreur mentionnée ainsi, alors j'ai décidé de voir si d'autres applications ont été affectées. J'ai à la fois Dropbox et Mint mis en place pour Touch ID. Effectivement, Touch ID ne fonctionnait pas pour eux non plus et ils se rabattaient sur les codes d'access.

    J'ai redémarré mon téléphone et il a recommencé à fonctionner, il semblerait donc que le Touch ID puisse s'interrompre et cesser de fonctionner. Je suis sur iOS 8.2 btw.

    Je suppose que la bonne façon de gérer cette condition est comme ces applications font et se rabat sur mot de passe / mot de passe.