iOS8 проверяет, есть ли у устройства Touch ID

LAContext имеет метод, чтобы проверить, может ли устройство оценить Touch ID и выдает сообщение об ошибке. Проблема в том, что одно и то же сообщение об ошибке "LAErrorPasscodeNotSet" выдается системой в двух случаях:

1) Если у пользователя есть Touch ID, но он отключен в настройках (iPhone 5s с iOS8)

2) Если на устройстве нет Touch ID (iPad с iOS8)

Q: Как проверить, поддерживает ли устройство Touch ID, но не включило его в настройках?

Обновить:

Создал тикет в Apple по поводу этой ошибки (ID# 18364575) и получил ответ:

" Инжиниринг установил, что эта проблема ведет себя как задумано, основываясь на следующей информации:

Если пароль не установлен, вы не сможете обнаружить присутствие Touch ID. После установки пароля код canEvaluatePolicy в конечном итоге вернет LAErrorTouchIDNotAvailable или LAErrorTouchIdNotEnrolled, и вы сможете обнаружить наличие / состояние Touch ID.

Если пользователи отключили пароль на телефоне с помощью Touch ID, они знали, что не смогут использовать Touch ID, поэтому приложениям не нужно обнаруживать присутствие Touch ID или продвигать функции на основе Touch ID. "

5 ответов

Решение

Возможно, вы могли бы написать свой собственный метод, чтобы проверить, на каком устройстве вы работаете, потому что, если возвращаемая ошибка будет такой же, было бы трудно точно определить, поддерживается ли Touch ID. Я хотел бы пойти с чем-то вроде этого:

int sysctlbyname(const char *, void *, size_t *, void *, size_t);

- (NSString *)getSysInfoByName:(char *)typeSpecifier
{
    size_t size;
    sysctlbyname(typeSpecifier, NULL, &size, NULL, 0);

    char *answer = malloc(size);
    sysctlbyname(typeSpecifier, answer, &size, NULL, 0);

    NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];

    free(answer);
    return results;
}

- (NSString *)modelIdentifier
{
    return [self getSysInfoByName:"hw.machine"];
}

Получив идентификатор модели, я бы просто проверил, равен ли идентификатор модели одной из моделей, поддерживающих Touch ID:

- (BOOL)hasTouchID
{
    NSArray *touchIDModels = @[ @"iPhone6,1", @"iPhone6,2", @"iPhone7,1", @"iPhone7,2", @"iPad5,3", @"iPad5,4", @"iPad4,7", @"iPad4,8", @"iPad4,9" ];

    NSString *model = [self modelIdentifier];

    return [touchIDModels containsObject:model];
}

Массив содержит все идентификаторы моделей, которые поддерживают Touch ID, а именно:

  • айфон 5с
  • Айфон 6
  • iPhone 6+
  • iPad Air 2
  • iPad Mini 3

Единственным недостатком этого метода является то, что после выпуска новых устройств с Touch ID массив моделей необходимо будет обновить вручную.

Здесь вы можете проверить Touch-ID и Face-ID как (с iOS 11+)

Использовать собственность biometryType из LAContext проверить и оценить доступную биометрическую политику. (Для аутентификации с помощью пароля, когда биометрический сбой, используйте: LAPolicyDeviceOwnerAuthentication)

Попробуйте это и увидите:

Objective-C:

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

NSError *error;


// For a passcode authentication , when biometric fails, use: LAPolicyDeviceOwnerAuthentication
//if ([laContext canEvaluatePolicy: LAPolicyDeviceOwnerAuthentication error:&error]) {
if ([laContext canEvaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {    
    if (error != NULL) {
        // handle error
    } else {

        if (@available(iOS 11, *)) {
            if (laContext.biometryType == LABiometryTypeFaceID) {
                //localizedReason = "Unlock using Face ID"
                NSLog(@"FaceId support");
            } else if (laContext.biometryType == LABiometryTypeTouchID) {
                //localizedReason = "Unlock using Touch ID"
                NSLog(@"TouchId support");
            } else {
                //localizedReason = "Unlock using Application Passcode"
                NSLog(@"No biometric support or Denied biometric support");
            }
        } else {
            // Fallback on earlier versions
        }


        [laContext evaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"Test Reason" reply:^(BOOL success, NSError * _Nullable error) {

            if (error != NULL) {
                // handle error
            } else if (success) {
                // handle success response
            } else {
                // handle false response
            }
        }];
    }
}

Swift:

let laContext = LAContext()
var error: NSError?
let biometricsPolicy = LAPolicy.deviceOwnerAuthentication //LAPolicy.deviceOwnerAuthenticationWithBiometrics

if laContext.isCredentialSet(LACredentialType.applicationPassword) {
    print("Passsword is set")
}

let localizedFallbackTitle = "Unlock Using Device Passcode"
let localizedCancelTitle = "Use Application Passcode"
if (laContext.canEvaluatePolicy(biometricsPolicy, error: &error)) {

    if let laError = error {
        print("laError - \(laError)")
        return
    }



    //print("biometricsPolicy - \(biometricsPolicy.rawValue)")

    UINavigationBar.appearance().tintColor = UIColor.red


    var localizedReason = "My Reason to be displayed on face id prompt"
    if #available(iOS 11.0, *) {
        if (laContext.biometryType == LABiometryType.faceID) {
            //localizedReason = "Unlock using Face ID"
            print("FaceId support")
        } else if (laContext.biometryType == LABiometryType.touchID) {
            //localizedReason = "Unlock using Touch ID"
            print("TouchId support")
        } else {
            //localizedReason = "Unlock using Application Passcode"
            print("No Biometric support")
        }
    } else {
        // Fallback on earlier versions
    }

    laContext.localizedFallbackTitle = localizedFallbackTitle
    laContext.localizedCancelTitle = localizedCancelTitle
    //laContext.localizedReason = "test loc reason"
    laContext.evaluatePolicy(biometricsPolicy, localizedReason: localizedReason, reply: { (isSuccess, error) in

        DispatchQueue.main.async(execute: {

            if let laError = error {
                print("laError - \(laError)")
            } else {
                if isSuccess {
                    print("sucess")
                } else {
                    print("failure")
                }
            }

        })
    })
}

В Свифт 3

fileprivate func deviceSupportsTouchId(success: @escaping () -> (), failure: @escaping (NSError) -> ()) {
    let context = LAContext()
    var authError: NSError?
    let touchIdSetOnDevice = context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &authError)

    if touchIdSetOnDevice {
        DispatchQueue.main.async {
             success()
        }
    }
    else {
        DispatchQueue.main.async {
             failure(error!)
        }
    }
}

deviceSupportsTouchId () возвращает Success, если устройство имеет функцию Touch Id.

Если нет, функция вернет ошибку, сообщив вам следующий код ошибки, если touchIDNotEnrolled еще не установлен.

LAError.Code.touchIDNotEnrolled.rawValue

Вы можете справиться с этим, используя это значение.

Вы можете узнать, поддерживает ли устройство биометрическое сканирование (touchID и faceID), проверив код ошибки, как показано ниже:

func deviceSupportsBiometricScanning() -> Bool {
    var authError: NSError?
    let _ = LAContext().canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError)
    return authError?.code != kLAErrorBiometryNotAvailable.hashValue
}

Интеграция Touch ID

Теперь мы переходим к основной части урока… интеграции Touch ID с приложением. Как оказалось, Apple сделала довольно стандартный код для доступа к Touch ID. Код взят из Local Authentication Framework и выглядит следующим образом:

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

NSError *authError = nil;

NSString *myLocalizedReasonString = @"Used for quick and secure access   to the test app";

 if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics    error:&authError]) {[myContext    evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
              localizedReason:myLocalizedReasonString
                        reply:^(BOOL success, NSError *error) {
          if (success) {
          // User authenticated successfully, take appropriate action
          } 
         else {
            // User did not authenticate successfully, look at error and take appropriate action
         }
    }];
 } 
 else {
// Could not evaluate policy; look at authError and present an appropriate message to user }

Давайте посмотрим на каждую строку, чтобы увидеть, что она делает:

Строка 1: здесь мы создаем объект LAContext. Класс LAContext отвечает за обработку контекста для аутентификации. Проще говоря, мы используем объект LAContext, чтобы проверить, доступен ли тип аутентификации. В этом уроке мы позже проверим "если" Touch ID является опцией.

Строка 2: нам нужен NSError, чтобы LAContext мог использовать его для возврата в случае ошибки.

Строка 3: мы устанавливаем строку NSS с описанием, которое она выводит на экран, чтобы пользователь знал, почему на экране появилось представление Touch ID.

Строка 5: здесь мы помещаем константу LAContext для использования, вызывая canEvaluatePolicy: метод и отправляя ей константу LAPolicy в качестве аргумента. В этом случае мы передаем LAPolicyDeviceOwnerAuthenticationWithBiometrics. Если это не удается, либо Touch ID не настроен на совместимом устройстве, либо Touch ID недоступен на устройстве... представьте, что на iPhone 4S, 5 или 5c запущено приложение. Кроме того, это не учитывает учетную запись устройства под управлением iOS 7, поэтому, если вы планируете запускать проверку подлинности с помощью отпечатка пальца в приложении, убедитесь, что вы работаете с совместимым устройством, а если нет, сделайте доступными другие параметры, такие как в качестве пароля на пин-код для доступа к приложению.

Строки 6, 7 и 8: если пользователь может аутентифицироваться с помощью биометрии, мы можем теперь вызвать метод valuPolicy для нашего объекта LAContext. Мы делаем это, передавая ту же самую константу, LAPolicyDeviceOwnerAuthenticationWithBiometrics, а также передавая нашу строку причины и затем определяя блок для ответа, который должен быть обработан.

В результате мы получим либо ДА, либо НЕТ. Если ДА, то в строке 10 мы помещаем код для положительного ответа. Аналогично, в строке 12 мы помещаем наш код ошибки.

Наконец, в строке 15 у нас есть оператор ELSE, который выполняется, если строка 5 не прошла тест, т. Е. Биометрия недоступна. Мы можем проверить указатель authError, чтобы получить причину и представить ее пользователю, если это необходимо.

Наконец, чтобы это не показывало ошибки, нам нужно импортировать локальную структуру аутентификации в наш проект:

Итак, давайте добавим этот код в наш проект. Откройте ViewController.m и в верхней части импортируйте локальную структуру аутентификации.

Для более подробной информации посетите эту ссылку: http://www.devfright.com/touch-id-tutorial-objective-c/

Другие вопросы по тегам