Reputation: 2299
I am integrating Touch ID access in one of my app. I have successfully integrated it. Here is that code:
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, ^{
dispatch_async(dispatch_get_main_queue(), ^{
LAContext *context = [[LAContext alloc] init];
isTouchExists = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil];
if (isTouchExists) {
NSString * keychainItemIdentifier;
NSString * keychainItemServiceName;
keychainItemIdentifier = @"fingerprintKeychainEntry";
keychainItemServiceName = [[NSBundle mainBundle] bundleIdentifier];
NSData * pwData = [@"the password itself does not matter" dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary * attributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
(__bridge id)(kSecClassGenericPassword), kSecClass,
keychainItemIdentifier, kSecAttrAccount,
keychainItemServiceName, kSecAttrService, nil];
CFErrorRef accessControlError = NULL;
SecAccessControlRef accessControlRef = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
kSecAccessControlUserPresence,
&accessControlError);
if (accessControlRef == NULL || accessControlError != NULL)
{
NSLog(@"Cannot create SecAccessControlRef to store a password with identifier “%@” in the key chain: %@.", keychainItemIdentifier, accessControlError);
}
attributes[(__bridge id)kSecAttrAccessControl] = (__bridge id)accessControlRef;
attributes[(__bridge id)kSecUseNoAuthenticationUI] = @YES;
attributes[(__bridge id)kSecValueData] = pwData;
CFTypeRef result;
OSStatus osStatus = SecItemAdd((__bridge CFDictionaryRef)attributes, &result);
if (osStatus != noErr)
{
NSError * error = [[NSError alloc] initWithDomain:NSOSStatusErrorDomain code:osStatus userInfo:nil];
NSLog(@"Adding generic password with identifier “%@” to keychain failed with OSError %d: %@.", keychainItemIdentifier, (int)osStatus, error);
}
//other my code for success
}
});
});
Now, If I remove all the fingerprints from settings in iPhone, This code will work and ask for passcode. So My question is:
how can I come to know that there is no any fingerprints added for Touch ID?
I don't want to show iOS device passcode screen as I have already built passcode screen for my app security. So is there any option to check device have atleast one fingerprint available for Touch ID access?
Thanks in advance.
======== EDIT 1 ===========
It is working on my side also. The issue is I need to check it each time when I am asking for Touch ID. I need to fetch status in viewWillAppear
or in applicationDidBecomeActive
each time whenever I want to use Touch ID access in app, as I am removing fingers run time, it may not reflecting in my code so I need to fetch each time.
Upvotes: 3
Views: 3123
Reputation: 16160
canEvaluatePolicy:error:
will be Error : LAErrorTouchIDNotEnrolled
Authentication could not start because Touch ID has no enrolled fingers.
Try:
LAContext *context = [[LAContext alloc] init];
NSError *error;
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"My Reason" reply:^(BOOL success, NSError * _Nullable error) {
}];
}else{
if (error.code == LAErrorTouchIDNotEnrolled) {
NSLog(@"Error: %@", error.localizedDescription);
}
}
Upvotes: 5
Reputation: 26
If there are no fingerprints registered, canEvaluatePolicy should return false.
Upvotes: 1