2014-09-24 19 views
16

LAContext ma metodę sprawdzania, czy urządzenie może ocenić identyfikator dotyku i wyświetla komunikat o błędzie. Problem jest to, że sam komunikat o błędzie „LAErrorPasscodeNotSet” jest podana przez system w dwóch przypadkach:iOS8 sprawdź, czy urządzenie ma Touch ID

1) Jeśli użytkownik posiada Touch ID, ale ona wyłączona w ustawieniach (iPhone 5S z systemów iOS 8)

2) Jeżeli urządzenie nie ma Touch ID (iPad z iOS8)

P: Jak sprawdzić, czy urządzenie obsługuje Touch ID, ale nie zostało włączone w ustawieniach?

Aktualizacja:

stworzył bilet do Apple dotyczące tego błędu (ID # 18364575) i otrzymała odpowiedź:

"Inżynieria ustaliła, że ​​kwestia ta zachowuje się zgodnie z oczekiwaniami na podstawie następujących informacji:

Jeśli hasło nie zostanie ustawione, nie będzie można wykryć obecności Touch ID. Po ustawieniu hasła canEvaluatePolicy w końcu zwróci LAErrorTouchIDNotAvailable lub LA ErrorTouchIdNotEnrolled i będziesz w stanie wykryć obecność/stan Touch ID.

Użytkownicy, którzy wyłączyli hasło na telefonie z Touch ID, wiedzieli, że nie będą mogli używać Touch ID, więc aplikacje nie muszą wykrywać obecności Touch ID ani promować funkcji opartych na Touch ID. "

+0

Ta odpowiedź inżyniera przypomina o tym, jak poprosić o pozwolenie na lokalizację (jeśli tak się stało wyłączyłeś lub nie autoryzowałeś aplikacji, a następnie nie pytaj ponownie). Problem polega na tym, że zakłada on zaznajomienie się z funkcjami i ustawieniami ze strony użytkownika, tj. Że zawsze będzie wiedział o ich ponownym włączeniu w Ustawieniach. Jednak z mojego doświadczenia wynika, że ​​jest to myślenie życzeniowe ... Użytkownicy w oczywisty sposób zapominają o tych rzeczach. – StephenT

+1

Wygląda na to, że Apple to naprawił: iOS 8.1 iPad 3 (bez dotyku) - LAErrorPasscodeNotSet, iOS 8.4 iPad 3 (bezdotykowo) - LAErrorTouchIDNotAvailable – Uladzimir

+0

Po prostu z ciekawości, o projekcie Twojej aplikacji: dlaczego miałbyś na względzie, czy urządzenie obsługuje TouchID , kiedy użytkownik w szczególności go wyłączył, a mimo to nie jest dostępny dla Twojej aplikacji? –

Odpowiedz

7

Może można napisać swoją własną metodę, aby sprawdzić, które urządzenia są uruchomione na, bo jeśli zwrócony błąd jest taki sam, trudno byłoby dowiedzieć się dokładnie, czy dotykowy ID jest obsługiwane. Pójdę z coś takiego:

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"]; 
} 

Po identyfikator modelu, chciałbym po prostu sprawdzić, czy identyfikator modelu równa jest jednym z modeli, które obsługują 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]; 
} 

tablicy zawiera wszystkie Model ID, który wspiera Touch ID, które są:

  • iPhone 5S
  • iPhone 6
  • iPhone 6+
  • iPad Air 2
  • iPad Mini 3

Jedyną wadą tej metody jest to, że po wypuszczeniu nowych urządzeń z Touch ID, tablica modeli będzie musiała zostać zaktualizowana ręcznie.

+1

Dzięki, Legoless. Zaproponowałem takie rozwiązanie. Ale jak zauważyłeś na końcu komunikatu - jest to rozwiązanie tymczasowe, więc powinienem je zaktualizować, gdy pojawi się nowe urządzenie. Mam nadzieję, że istnieje inny sposób, bez ręcznych aktualizacji. – 1ce

+0

Możemy łatwo założyć, że wszystkie nowe iPhone'y będą również miały Touch ID, więc możemy dodać logikę, że jeśli model iPhone'a jest wyższy niż 6, x może zwrócić TAK. Musisz tylko uważać, jeśli iPad otrzyma Touch ID, ale aktualizacja tego raz w roku nie powinna stanowić problemu - poza tym, że i tak już aktualizujesz aplikację dla nowego iOS. Trzeba tylko uważać, aby nie zostało zapomniane. – Legoless

+0

Wiemy, że nowe urządzenia będą obsługiwać Touch ID, więc możemy po prostu sprawdzić, czy jego iPhone 4S i 5 to wiemy, że nie obsługuje Touch ID. Ponieważ iPhone 4 lub poniżej nie może przejść do systemu iOS 8, a jego błąd w systemie iOS8 nie będzie mieć wartości null. W ten sposób nie trzeba aktualizować aplikacji po ogłoszeniu nowych urządzeń. – Paragon

1

Integracja dotykowy ID

Teraz przejdziemy do głównej części tutorialu ... Touch ID integracji z aplikacją. Jak się okazało, Apple opracował dość standardowy kod dostępu do Touch ID.Kod pochodzi z lokalnej Framework uwierzytelniania i przedstawia się następująco:

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 } 

Pozwala spojrzeć na każdej linii, aby zobaczyć, co robi:

Linia 1: Tutaj możemy utworzyć obiekt LAContext. Klasa LAContext odpowiada za obsługę kontekstu uwierzytelniania. Mówiąc prościej, używamy obiektu LAContext w celu sprawdzenia, czy dostępny jest typ uwierzytelniania. W przypadku tego samouczka później sprawdzimy, czy opcja "touch" jest opcją.

Wiersz 2: Potrzebujemy NSError, aby LAContext mógł go użyć, aby powrócić, jeśli wystąpił błąd.

Linia 3: Ustawiamy NSString z opisem umieszczonym na ekranie, aby poinformować użytkownika, dlaczego na ekranie pojawił się ekran dotykowy.

Wiersz 5: W tym miejscu wstawiamy stałą LAContext, wywołując metodę canEvaluatePolicy: i wysyłając jej stałą LAPolicy jako argument. W takim przypadku przekazujemy LAPolicyDeviceOwnerAuthenticationWithBiometrics. Jeśli to się nie powiedzie, albo identyfikator dotykowy nie jest skonfigurowany na kompatybilnym urządzeniu, albo dotykowy ID nie jest dostępny na urządzeniu ... pomyśl o iPhone 4S, 5 lub 5c z uruchomioną aplikacją. Nie uwzględnia to również urządzenia z systemem iOS 7, więc jeśli planujesz uruchomić uwierzytelnianie odcisków palców w aplikacji, upewnij się, że sprawdzasz, czy pracujesz na zgodnym urządzeniu, a jeśli nie, udostępnij inne opcje, takie jak jako hasło do kodu PIN, aby uzyskać dostęp do aplikacji.

Linie 6, 7 i 8: Jeśli użytkownik może uwierzytelnić się za pomocą danych biometrycznych, możemy teraz wywołać metodę evaluatePolicy na naszym obiekcie LAContext. Robimy to, przekazując tę ​​samą stałą, LAPolicyDeviceOwnerAuthenticationWithBiometrics, jak również przekazując nasz ciąg powodu, a następnie określając blok dla odpowiedzi, którą należy obsłużyć.

Otrzymamy w rezultacie TAK lub NIE. Jeśli TAK, to linia 10 jest tam, gdzie umieszczamy kod dla pozytywnej odpowiedzi. Podobnie, wiersz 12 jest tam, gdzie umieszczamy nasz kod błędu.

Wreszcie w linii 15 mamy instrukcję ELSE, która działa, jeśli wiersz 5 nie przejdzie testu ... tzn. Dane biometryczne nie są dostępne. Możemy sprawdzić wskaźnik authError, aby uzyskać powód i przedstawić go użytkownikowi, jeśli to konieczne.

Wreszcie, aby uzyskać to, by nie pokazać błędy, musimy importować lokalnej ramy uwierzytelniania się do naszego projektu:

Tak, pozwala dodać ten kod do naszego projektu. Otwórz ViewController.m i u góry, zaimportuj lokalny framework uwierzytelniania.

więcej szczegółów wizyty link: http://www.devfright.com/touch-id-tutorial-objective-c/

+0

Twoja odpowiedź powinna być prosta, a nie kompletny samouczek. –

+0

** Ramraj T, jeśli potrzebujesz więcej informacji o urządzeniu ma Touch ID niż odwiedź ten samouczek [link] (http://code.tutsplus.com/tutorials/ios-8-integrating-touch-id--cms-21949) na pewno ci pomoże ** –

1

w Swift 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() zwracają sukcesu, jeśli urządzenie posiada dotykowy zdolności id.

Jeśli nie, funkcja zwróci błąd, podając następujący kod błędu, jeśli touchIDNotEnrolled nie jest jeszcze ustawiony.

LAError.Code.touchIDNotEnrolled.rawValue

można obsługiwać go za pomocą tej wartości.

0

Tutaj można sprawdzić, Touch-ID i Face-ID obu (z iOS 11+)

Zastosowanie nieruchomość biometryType od LAContext sprawdzić i ocenić dostępne politykę biometrycznych. (Podczas uwierzytelniania kodem, gdy biometryczne zawiedzie, zużyć LAPolicyDeviceOwnerAuthentication)

Spróbuj i patrz

celu 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") 
       } 
      } 

     }) 
    }) 
} 
Powiązane problemy