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.
Asked
Active
Viewed 3,273 times
7
-
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 Answers
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