7

I have followed the guidelines and also the example for Touch ID API from Apple documentation. I have used the example in my applications. I could able to login using Touch ID. But the problem is its responsive is very very slow. After I put my finger on the Touch ID , at least 10 seconds I have to wait to get verify success/failure. I have used the code in app delegate file. I have also tested with different apps but the result is the same "delayed response". Guys please help me in this case.

user4150758
  • 384
  • 4
  • 17
  • Should I write the code in dispatch queue? – user4150758 Oct 17 '14 at 03:35
  • I've noticed this as well. I followed Apple's example and it is taking a fair amount of seconds before I get that callback. Hope someone has some answers because Apple's documentation on this is lackluster. – Inertiatic Oct 17 '14 at 18:40
  • Yeah. But I'm not sure how come 1password does it flawlessly. – user4150758 Oct 17 '14 at 18:41
  • Oh duh, can't believe I didn't think of this. The supplied answer from Vishal is correct. I just thought it was a copy and paste of Apple's code, but we need to do everything with UI on the main thread, which he/she did on the success block. – Inertiatic Oct 17 '14 at 18:56

3 Answers3

23
LAContext *myContext = [[LAContext alloc] init];

NSError *authError = nil;

NSString *myLocalizedReasonString = <#String explaining why app needs authentication#>;

if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {

    [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
              localizedReason:myLocalizedReasonString
                        reply:^(BOOL success, NSError *error) { 

                            if (success) {
                                   // User authenticated successfully, take appropriate action
                                   dispatch_async(dispatch_get_main_queue(), ^{
                                          // write all your code here
                               });
                            } else {
                                   // User did not authenticate successfully, look at error and take appropriate action

                               switch (error.code) {
                                   case LAErrorAuthenticationFailed:
                                       NSLog(@"Authentication Failed");
                                       break;

                                   case LAErrorUserCancel:
                                       NSLog(@"User pressed Cancel button");
                                       break;

                                   case LAErrorUserFallback:
                                       NSLog(@"User pressed \"Enter Password\"");
                                       break;

                                   default:
                                       NSLog(@"Touch ID is not configured");
                                       break;
                               }

                               NSLog(@"Authentication Fails");
                            }
                        }];
} else {
    // Could not evaluate policy; look at authError and present an appropriate message to user
}
sKhan
  • 9,694
  • 16
  • 55
  • 53
Vishal Gandhi
  • 256
  • 2
  • 3
7

You have to display the alertviews in the main thread with

dispatch_async(dispatch_get_main_queue(), ^{ 
//update ui
});

LAContext *context = [[LAContext alloc] init];

NSError *error = nil;

if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
// Authenticate User

NSError *error = nil;
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
  [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
          localizedReason:@"Please verify that you are the device owner in order to place the order"
                    reply:^(BOOL success, NSError *error) {
                      dispatch_async(dispatch_get_main_queue(), ^{
                        if (error) {
                          UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                                          message:@"There was a problem verifying your identity."
                                                                         delegate:nil
                                                                cancelButtonTitle:@"Ok"
                                                                otherButtonTitles:nil];
                          [alert show];
                          return;
                        }

                        if (success) {
                          UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success"
                                                                          message:@"You are the device owner!"
                                                                         delegate:nil
                                                                cancelButtonTitle:@"Ok"
                                                                otherButtonTitles:nil];
                          [alert show];

                        } else {
                          UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                                          message:@"You are not the device owner."
                                                                         delegate:nil
                                                                cancelButtonTitle:@"Ok"
                                                                otherButtonTitles:nil];
                          [alert show];
                        }
                      });
                    }];
}

} else {

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                message:@"Your device cannot authenticate using TouchID."
                                               delegate:nil
                                      cancelButtonTitle:@"Ok"
                                      otherButtonTitles:nil];
[alert show];

}

Bibo Lan
  • 71
  • 2
  • 3
1

As other said, you have to do UI thing on the main thread, for Swift 3.0 it's:

myContext.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString) { (success, evaluateError) in
            DispatchQueue.main.async {
                    if (success) {
                        //success
                    } else {
                        //failure
                    }
                }
            }
Michał Kwiecień
  • 2,734
  • 1
  • 20
  • 23