C# から直接 Swift のコードを呼び出す、の例として生体認証(TouchID、FaceID)を実装します。
Swift ド素人が書いた適当コードなので、色々と目を瞑ってください……。
GitHub
コード
iOSAuthentication.cs
using UnityEngine; using System.Runtime.InteropServices; using System; public class iOSAuthentication : MonoBehaviour { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void CallbackDelegate([MarshalAs(UnmanagedType.I4)] Int32 num); [DllImport("__Internal", EntryPoint = "registerAuthCallback")] static extern void RegisterAuthCallback([MarshalAs(UnmanagedType.FunctionPtr)] CallbackDelegate callback); [DllImport("__Internal", EntryPoint = "authentication")] static extern long Authentication(); void Start() { RegisterAuthCallback(callback); } public void onPressButton() { Authentication(); } [AOT.MonoPInvokeCallbackAttribute(typeof(CallbackDelegate))] static void callback(Int32 num) { Debug.Log($"call native code: {num}"); } }
Plugin/iOS/iOSAuthentication.swift
import Foundation import LocalAuthentication public typealias CallbackDelegate = @convention(c) (Int32) -> Void public class iOSAuthentication { static private var authCallbackDelegate: CallbackDelegate? = nil; public static func registerAuthCallback(_ delegate: @escaping CallbackDelegate) { authCallbackDelegate = delegate } public static func authentication() { var description: String = "サインイン" let context = LAContext() context.localizedFallbackTitle = "他の方法を試す" var error: NSError? // Face ID, Touch IDが利用できるデバイスか確認する if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { // Face ID, Touch IDが利用できる場合は認証用ダイアログを表示 context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: description, reply: { success, evaluateError in if (success) { // 認証成功 switch context.biometryType { case .faceID: authCallbackDelegate?(1) break case .touchID: authCallbackDelegate?(1) break case .none: // Face ID, Touch IDが利用出来ない (unknown) authCallbackDelegate?(0) break @unknown default: authCallbackDelegate?(0) break } } else { // 認証失敗 authCallbackDelegate?(0) } } ) } else { // Face ID, Touch IDが利用出来ない authCallbackDelegate?(-1) } } } @_cdecl("registerAuthCallback") public func registerAuthCallback(_ delegate: @escaping CallbackDelegate) { return iOSAuthentication.registerAuthCallback(delegate) } @_cdecl("authentication") public func authentication() { return iOSAuthentication.authentication() }
Editor/OnPostBuildProcess.cs
FaceID を有効にするためには、Info.plist にキーを用意しておく必要があります。
using UnityEngine; using UnityEditor; using UnityEditor.Callbacks; using System.IO; #if UNITY_IOS using UnityEditor.iOS.Xcode; #endif public class OnPostBuildProcess : MonoBehaviour { [PostProcessBuild] public static void OnPostProcessBuild(BuildTarget buildTarget, string path) { if (buildTarget == BuildTarget.iOS) { processForiOS(path); } } static void processForiOS(string path) { #if UNITY_IOS var plistPath = Path.Combine(path, "Info.plist"); var plist = new PlistDocument(); plist.ReadFromFile(plistPath); var root = plist.root; root.SetString("NSFaceIDUsageDescription", "認証に必要"); plist.WriteToFile(plistPath); #endif } }
実行
TouchID、FaceID 両方に対応しています。
Authentification() で認証スタート、認証画面が終わると RegisterAuthCallback() で設定したコールバックに値を返します。
-1 .. TouchID、FaceID が許可されていない
0 .. 認証失敗
1 .. 認証成功
シミュレーターで確認可能
Xcode のシミュレーターで確認するのがお手軽です(Face ID は実機で見た方がいいかも)。
TouchID、FaceID を許可する
Features > Touch(Face)ID > Enrolled
Enrolled に✓マークがつくと、TouchID・FaceIDの動作を確認することができます。
判定の OK、NG
Features > Touch(Face)ID > Matching Touch(Face)
Features > Touch(Face)ID > Non-matching Touch(Face)
認証判定の OK、NG をシミュレートするにはこの2つのコマンドを選択します。
AppStore に提出する場合
一点問題があります。それについては別の記事にしましたので、必要に応じてご覧ください。