I\'m currently developing an iOS app that enables users to log in to the app using TouchID, but firstly they must set up a password inside the app first. Problem is, to show
Here is a bit tedious way to figure out if device has physical touch id sensor.
+ (BOOL)isTouchIDExist {
if(![LAContext class]) //Since this mandotory class is not there, that means there is no physical touch id.
return false;
//Get the current device model name
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *model = malloc(size);
sysctlbyname("hw.machine", model, &size, NULL, 0);
NSString *deviceModel = [NSString stringWithCString:model encoding:NSUTF8StringEncoding];
//Devices that does not support touch id
NSArray *deviceModelsWithoutTouchID = [[NSArray alloc]
initWithObjects:
@"iPhone1,1", //iPhone
@"iPhone1,2", //iPhone 3G
@"iPhone2,1", //iPhone 3GS
@"iPhone3,1", //iPhone 4
@"iPhone3,2",
@"iPhone3,3",
@"iPhone4,1", //iPhone 4S
@"iPhone5,1", //iPhone 5
@"iPhone5,2",
@"iPhone5,3", //iPhone 5C
@"iPhone5,4",
@"iPod1,1", //iPod
@"iPod2,1",
@"iPod3,1",
@"iPod4,1",
@"iPod5,1",
@"iPod7,1",
@"iPad1,1", //iPad
@"iPad2,1", //iPad 2
@"iPad2,2",
@"iPad2,3",
@"iPad2,4",// iPad mini 1G
@"iPad2,5",
@"iPad2,5",
@"iPad2,7",
@"iPad3,1", //iPad 3
@"iPad3,2",
@"iPad3,3",
@"iPad3,4", //iPad 4
@"iPad3,5",
@"iPad3,6",
@"iPad4,1", //iPad Air
@"iPad4,2",
@"iPad4,3",
@"iPad4,4", //iPad mini 2
@"iPad4,5",
@"iPad4,6",
@"iPad4,7",
nil];
return ![deviceModelsWithoutTouchID containsObject:deviceModel];
}
Reference: https://www.theiphonewiki.com/wiki/Models https://en.wikipedia.org/wiki/IOS
Following is the way by which you can identify whether Touch Id or Face ID is supported on the device
open class LocalAuth: NSObject {
public static let shared = LocalAuth()
private override init() {}
var laContext = LAContext()
func canAuthenticate() -> Bool {
var error: NSError?
let hasTouchId = laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
return hasTouchId
}
func hasTouchId() -> Bool {
if canAuthenticate() && laContext.biometryType == .touchID {
return true
}
return false
}
func hasFaceId() -> Bool {
if canAuthenticate() && laContext.biometryType == .faceID {
return true
}
return false
}
}
And following is the Usage of the above-shared code
if LocalAuth.shared.hasTouchId() {
print("Has Touch Id")
} else if LocalAuth.shared.hasFaceId() {
print("Has Face Id")
} else {
print("Device does not have Biometric Authentication Method")
}
I know this is a question from last year, but this solution does not make what you need? (Swift code)
if #available(iOS 8.0, *) {
var error: NSError?
let hasTouchID = LAContext().canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error)
//Show the touch id option if the device has touch id hardware feature (even if the passcode is not set or touch id is not enrolled)
if(hasTouchID || (error?.code != LAError.TouchIDNotAvailable.rawValue)) {
touchIDContentView.hidden = false
}
}
Then, when the user presses the button to log in with touch id:
@IBAction func loginWithTouchId() {
let context = LAContext()
var error: NSError?
let reasonString = "Log in with Touch ID"
if (context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error)) {
[context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in
//Has touch id. Treat the success boolean
})]
} else {
//Then, if the user has touch id but is not enrolled or the passcode is not set, show a alert message
switch error!.code{
case LAError.TouchIDNotEnrolled.rawValue:
//Show alert message to inform that touch id is not enrolled
break
case LAError.PasscodeNotSet.rawValue:
//Show alert message to inform that passcode is not set
break
default:
// The LAError.TouchIDNotAvailable case.
// Will not catch here, because if not available, the option will not visible
}
}
}
Hope it helps!
For iOS 11+ you can use biometryType: LABiometryType
of LAContext
. More from Apple documentation:
/// Indicates the type of the biometry supported by the device.
///
/// @discussion This property is set only when canEvaluatePolicy succeeds for a biometric policy.
/// The default value is LABiometryTypeNone.
@available(iOS 11.0, *)
open var biometryType: LABiometryType { get }
@available(iOS 11.0, *)
public enum LABiometryType : Int {
/// The device does not support biometry.
@available(iOS 11.2, *)
case none
/// The device does not support biometry.
@available(iOS, introduced: 11.0, deprecated: 11.2, renamed: "LABiometryType.none")
public static var LABiometryNone: LABiometryType { get }
/// The device supports Touch ID.
case touchID
/// The device supports Face ID.
case faceID
}
In conclusion of the discussion below, for the time being it is not possible to determine whether a device actually supports TouchID or not when the user hasn't set up passcode on their device.
I have reported this TouchID flaw on the Apple bug reporter. Those who want to follow the issue can see it on Open Radar here: http://www.openradar.me/20342024
Thanks @rckoenes for the input :)
EDIT
Turns out that someone has reported a similar issue already (#18364575). Here is Apple's reply regarding the issue:
"Engineering has determined that this issue behaves as intended based on the following information:
If passcode is not set, you will not be able to detect Touch ID presence. Once the passcode is set, canEvaluatePolicy will eventually return LAErrorTouchIDNotAvailable or LAErrorTouchIdNotEnrolled and you will be able to detect Touch ID presence/state.
If users have disabled passcode on phone with Touch ID, they knew that they will not be able to use Touch ID, so the apps don't need to detect Touch ID presence or promote Touch ID based features. "
So..... the final answer from Apple is No. :(
Note: similar StackOverflow question from the person who reported this -> iOS8 check if device has Touch ID (wonder why I didn't find this question before despite my extensive searching...)
The correct way to detect if TouchID is available:
BOOL hasTouchID = NO;
// if the LAContext class is available
if ([LAContext class]) {
LAContext *context = [LAContext new];
NSError *error = nil;
hasTouchId = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
}
Sorry it is in Objective-C, you might have to translate it to C#.
You should refrain from checking the system version and just check whether or not the class or methods are available.