Face IDとTouch IDの対応は意外と簡単！

##はじめに
FaceIDについて調べたのでメモです。

##Info.plistに`NSFaceIDUsageDescription`を追加
`NSFaceIDUsageDescription`で許可を求めるようにします。

```ruby:Info.plist
	<key>NSFaceIDUsageDescription</key>
	<string>Face IDで認証します。</string>
```

Source Code
<img width="300" alt="スクリーンショット 2017-12-02 17.21.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/f7730131-b687-7e1f-15f4-a5e55eeb8273.png">

Property List
<img width="300" alt="スクリーンショット 2017-12-02 17.20.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/89206/090304eb-4406-4730-58c9-044ad311de8b.png">

####注意
許可を求めないと下記のようなアラートが出てきます。
Face IDに対応していないと言われます。(Face ID認証はされます)
<img width="300" alt="IMG_0855 2.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/89206/ec95f6ce-b609-8f6f-ded6-5439489ad03a.png">

`NSFaceIDUsageDescription `を追加すると下記のようなアラートに変わります。
<img width="300" alt="IMG_0856 3.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/89206/f78dd354-0a47-2802-dd26-1709d2ad8f3a.png">

##コード
下記のようなコードでiPhone XならFace ID、Touch IDデバイスならToutch IDで認証します。
認証するためのアラートやアニメーションは勝手に出てきます。

```ruby:Swift
        let context = LAContext()
        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
            let localizedReason = "指紋認証を行なってください。"
            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: localizedReason, reply: { success, error in
                if let error = error {
                    switch LAError(_nsError: error as NSError) {
                    case LAError.userCancel:
                        // キャンセル
                        reply(.cancel)
                    case LAError.userFallback:
                        // パスコードを入力
                        reply(.userFallback)
                    case LAError.authenticationFailed:
                        reply(.error(.authenticationFailed))
                    case LAError.passcodeNotSet:
                        reply(.error(.passcodeNotSet))
                    case LAError.systemCancel:
                        reply(.error(.systemCancel))
                    default:
                        reply(.error(.unknownError))
                    }
                } else if success {
                    reply(.success)
                } else {
                    reply(.error(.unknownError))
                }
            })
        } else {
            reply(.error(.notSupport))
        }
```

##Face IDかTouch IDかを判断
認証するためのボタンをFace IDとTouch IDで分けたい場合は、どちらで認証されるのかを知る必要があります。
その場合、biometryTypeを使います。
iOS11から使用できるメソッドなので`if #available(iOS 11.0, *) {`とする必要があり、context.canEvaluatePolicyがtrueでiOS10の場合はTouch IDだと判断できます。

```ruby:Swift
        let context = LAContext()
        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
            if #available(iOS 11.0, *) {
                switch context.biometryType {
                case .typeTouchID:
                    return .touchId
                case .typeFaceID:
                    return .faceId
                case .none:
                    return .none
                }
            } else {
                return .touchId
            }
        } else {
            return .none
        }
```

##GitHub
LocalAuthenticationManagerというクラスで処理を書いています。
https://github.com/hideyukitone/LocalAuthenticationSample

##最後に
意外と簡単でした。
少ない工数で最新の技術を取り入れているように見えるのでオススメです！