├── FaceIDAuthentication
├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── AppDelegate.swift
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── ViewController.swift
├── Info.plist
├── SceneDelegate.swift
└── BiometricIDAuth.swift
├── README.md
└── FaceIDAuthentication.xcodeproj
├── project.xcworkspace
├── contents.xcworkspacedata
├── xcuserdata
│ ├── shahrukhalam.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ └── shahrukh.alam.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── xcuserdata
├── shahrukh.alam.xcuserdatad
│ └── xcschemes
│ │ └── xcschememanagement.plist
└── shahrukhalam.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
└── project.pbxproj
/FaceIDAuthentication/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FaceIDAuthentication
2 |
3 | Checkout full article on [Medium](https://medium.com/@alam.shahrukh786/integrating-face-id-touch-id-3ab409c72519)
4 |
--------------------------------------------------------------------------------
/FaceIDAuthentication.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/FaceIDAuthentication.xcodeproj/project.xcworkspace/xcuserdata/shahrukhalam.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahrukhalam/FaceIDAuthentication/HEAD/FaceIDAuthentication.xcodeproj/project.xcworkspace/xcuserdata/shahrukhalam.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/FaceIDAuthentication.xcodeproj/project.xcworkspace/xcuserdata/shahrukh.alam.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahrukhalam/FaceIDAuthentication/HEAD/FaceIDAuthentication.xcodeproj/project.xcworkspace/xcuserdata/shahrukh.alam.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/FaceIDAuthentication.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/FaceIDAuthentication.xcodeproj/xcuserdata/shahrukh.alam.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | FaceIDAuthentication.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/FaceIDAuthentication.xcodeproj/xcuserdata/shahrukhalam.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | FaceIDAuthentication.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/FaceIDAuthentication/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // FaceIDAuthentication
4 | //
5 | // Created by Shahrukh Alam on 10/05/20.
6 | // Copyright © 2020 Shahrukh Alam. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 |
15 |
16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17 | // Override point for customization after application launch.
18 | return true
19 | }
20 |
21 | // MARK: UISceneSession Lifecycle
22 |
23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
24 | // Called when a new scene session is being created.
25 | // Use this method to select a configuration to create the new scene with.
26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
27 | }
28 |
29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
30 | // Called when the user discards a scene session.
31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
33 | }
34 |
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/FaceIDAuthentication/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/FaceIDAuthentication/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/FaceIDAuthentication/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // FaceIDAuthentication
4 | //
5 | // Created by Shahrukh Alam on 10/05/20.
6 | // Copyright © 2020 Shahrukh Alam. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | class ViewController: UIViewController {
11 |
12 | @IBOutlet weak var verifyButton: UIButton!
13 | private let biometricIDAuth = BiometricIDAuth()
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 | // Do any additional setup after loading the view.
18 |
19 | verifyButton.setImage(UIImage(systemName: "faceid"), for: .normal)
20 | }
21 |
22 | @IBAction func verifyDidTap(_ sender: UIButton) {
23 | biometricIDAuth.canEvaluate { (canEvaluate, _, canEvaluateError) in
24 | guard canEvaluate else {
25 | alert(title: "Error",
26 | message: canEvaluateError?.localizedDescription ?? "Face ID/Touch ID may not be configured",
27 | okActionTitle: "Darn!")
28 | return
29 | }
30 |
31 | biometricIDAuth.evaluate { [weak self] (success, error) in
32 | guard success else {
33 | self?.alert(title: "Error",
34 | message: error?.localizedDescription ?? "Face ID/Touch ID may not be configured",
35 | okActionTitle: "Darn!")
36 | return
37 | }
38 |
39 | self?.alert(title: "Success",
40 | message: "You have a free pass, now",
41 | okActionTitle: "Yay!")
42 | }
43 | }
44 | }
45 |
46 | func alert(title: String, message: String, okActionTitle: String) {
47 | let alertView = UIAlertController(title: title,
48 | message: message,
49 | preferredStyle: .alert)
50 | let okAction = UIAlertAction(title: okActionTitle, style: .default)
51 | alertView.addAction(okAction)
52 | present(alertView, animated: true)
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/FaceIDAuthentication/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSFaceIDUsageDescription
6 | We use Face ID/Touch ID to ease authentication of Passcode
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UIApplicationSceneManifest
26 |
27 | UIApplicationSupportsMultipleScenes
28 |
29 | UISceneConfigurations
30 |
31 | UIWindowSceneSessionRoleApplication
32 |
33 |
34 | UISceneConfigurationName
35 | Default Configuration
36 | UISceneDelegateClassName
37 | $(PRODUCT_MODULE_NAME).SceneDelegate
38 | UISceneStoryboardFile
39 | Main
40 |
41 |
42 |
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 | UISupportedInterfaceOrientations~ipad
59 |
60 | UIInterfaceOrientationPortrait
61 | UIInterfaceOrientationPortraitUpsideDown
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/FaceIDAuthentication/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // FaceIDAuthentication
4 | //
5 | // Created by Shahrukh Alam on 10/05/20.
6 | // Copyright © 2020 Shahrukh Alam. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
12 |
13 | var window: UIWindow?
14 |
15 |
16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
20 | guard let _ = (scene as? UIWindowScene) else { return }
21 | }
22 |
23 | func sceneDidDisconnect(_ scene: UIScene) {
24 | // Called as the scene is being released by the system.
25 | // This occurs shortly after the scene enters the background, or when its session is discarded.
26 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
28 | }
29 |
30 | func sceneDidBecomeActive(_ scene: UIScene) {
31 | // Called when the scene has moved from an inactive state to an active state.
32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
33 | }
34 |
35 | func sceneWillResignActive(_ scene: UIScene) {
36 | // Called when the scene will move from an active state to an inactive state.
37 | // This may occur due to temporary interruptions (ex. an incoming phone call).
38 | }
39 |
40 | func sceneWillEnterForeground(_ scene: UIScene) {
41 | // Called as the scene transitions from the background to the foreground.
42 | // Use this method to undo the changes made on entering the background.
43 | }
44 |
45 | func sceneDidEnterBackground(_ scene: UIScene) {
46 | // Called as the scene transitions from the foreground to the background.
47 | // Use this method to save data, release shared resources, and store enough scene-specific state information
48 | // to restore the scene back to its current state.
49 | }
50 |
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/FaceIDAuthentication/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/FaceIDAuthentication/BiometricIDAuth.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BiometricIDAuth.swift
3 | // FaceIDAuthentication
4 | //
5 | // Created by Shahrukh Alam on 23/05/20.
6 | // Copyright © 2020 Shahrukh Alam. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import LocalAuthentication
11 |
12 | class BiometricIDAuth {
13 | enum BiometricType {
14 | case none
15 | case touchID
16 | case faceID
17 | case unknown
18 | }
19 |
20 | enum BiometricError: LocalizedError {
21 | case authenticationFailed
22 | case userCancel
23 | case userFallback
24 | case biometryNotAvailable
25 | case biometryNotEnrolled
26 | case biometryLockout
27 | case unknown
28 |
29 | var errorDescription: String? {
30 | switch self {
31 | case .authenticationFailed: return "There was a problem verifying your identity."
32 | case .userCancel: return "You pressed cancel."
33 | case .userFallback: return "You pressed password."
34 | case .biometryNotAvailable: return "Face ID/Touch ID is not available."
35 | case .biometryNotEnrolled: return "Face ID/Touch ID is not set up."
36 | case .biometryLockout: return "Face ID/Touch ID is locked."
37 | case .unknown: return "Face ID/Touch ID may not be configured"
38 | }
39 | }
40 | }
41 |
42 | private let context = LAContext()
43 | private let policy: LAPolicy
44 | private let localizedReason: String
45 |
46 | private var error: NSError?
47 |
48 | init(policy: LAPolicy = .deviceOwnerAuthenticationWithBiometrics,
49 | localizedReason: String = "Verify your Identity",
50 | localizedFallbackTitle: String = "Enter App Password") {
51 | self.policy = policy
52 | self.localizedReason = localizedReason
53 | context.localizedFallbackTitle = localizedFallbackTitle
54 | context.localizedCancelTitle = "Touch me not"
55 | }
56 |
57 | func canEvaluate(completion: (Bool, BiometricType, BiometricError?) -> Void) {
58 | // Asks Context if it can evaluate a Policy
59 | // Passes an Error pointer to get error code in case of failure
60 | guard context.canEvaluatePolicy(policy, error: &error) else {
61 | // Extracts the LABiometryType from Context
62 | // Maps it to our BiometryType
63 | let type = biometricType(for: context.biometryType)
64 |
65 | // Unwraps Error
66 | // If not available, sends false for Success & nil in BiometricError
67 | guard let error = error else {
68 | return completion(false, type, nil)
69 | }
70 |
71 | // Maps error to our BiometricError
72 | return completion(false, type, biometricError(from: error))
73 | }
74 |
75 | // Context can evaluate the Policy
76 | completion(true, biometricType(for: context.biometryType), nil)
77 | }
78 |
79 | func evaluate(completion: @escaping (Bool, BiometricError?) -> Void) {
80 | // Asks Context to evaluate a Policy with a LocalizedReason
81 | context.evaluatePolicy(policy, localizedReason: localizedReason) { [weak self] success, error in
82 | // Moves to the main thread because completion triggers UI changes
83 | DispatchQueue.main.async {
84 | if success {
85 | // Context successfully evaluated the Policy
86 | completion(true, nil)
87 | } else {
88 | // Unwraps Error
89 | // If not available, sends false for Success & nil for BiometricError
90 | guard let error = error else { return completion(false, nil) }
91 |
92 | // Maps error to our BiometricError
93 | completion(false, self?.biometricError(from: error as NSError))
94 | }
95 | }
96 | }
97 | }
98 |
99 | private func biometricType(for type: LABiometryType) -> BiometricType {
100 | switch type {
101 | case .none:
102 | return .none
103 | case .touchID:
104 | return .touchID
105 | case .faceID:
106 | return .faceID
107 | @unknown default:
108 | return .unknown
109 | }
110 | }
111 |
112 | private func biometricError(from nsError: NSError) -> BiometricError {
113 | let error: BiometricError
114 |
115 | switch nsError {
116 | case LAError.authenticationFailed:
117 | error = .authenticationFailed
118 | case LAError.userCancel:
119 | error = .userCancel
120 | case LAError.userFallback:
121 | error = .userFallback
122 | case LAError.biometryNotAvailable:
123 | error = .biometryNotAvailable
124 | case LAError.biometryNotEnrolled:
125 | error = .biometryNotEnrolled
126 | case LAError.biometryLockout:
127 | error = .biometryLockout
128 | default:
129 | error = .unknown
130 | }
131 |
132 | return error
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/FaceIDAuthentication.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0186D160247905E40093C08D /* BiometricIDAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0186D15F247905E40093C08D /* BiometricIDAuth.swift */; };
11 | 95075E9C2468253F0079BF98 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95075E9B2468253F0079BF98 /* AppDelegate.swift */; };
12 | 95075E9E2468253F0079BF98 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95075E9D2468253F0079BF98 /* SceneDelegate.swift */; };
13 | 95075EA02468253F0079BF98 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95075E9F2468253F0079BF98 /* ViewController.swift */; };
14 | 95075EA32468253F0079BF98 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 95075EA12468253F0079BF98 /* Main.storyboard */; };
15 | 95075EA52468254D0079BF98 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95075EA42468254D0079BF98 /* Assets.xcassets */; };
16 | 95075EA82468254D0079BF98 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 95075EA62468254D0079BF98 /* LaunchScreen.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXFileReference section */
20 | 0186D15F247905E40093C08D /* BiometricIDAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BiometricIDAuth.swift; sourceTree = ""; };
21 | 95075E982468253F0079BF98 /* FaceIDAuthentication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FaceIDAuthentication.app; sourceTree = BUILT_PRODUCTS_DIR; };
22 | 95075E9B2468253F0079BF98 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
23 | 95075E9D2468253F0079BF98 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
24 | 95075E9F2468253F0079BF98 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
25 | 95075EA22468253F0079BF98 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
26 | 95075EA42468254D0079BF98 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | 95075EA72468254D0079BF98 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | 95075EA92468254D0079BF98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 95075E952468253F0079BF98 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 95075E8F2468253F0079BF98 = {
43 | isa = PBXGroup;
44 | children = (
45 | 95075E9A2468253F0079BF98 /* FaceIDAuthentication */,
46 | 95075E992468253F0079BF98 /* Products */,
47 | );
48 | sourceTree = "";
49 | };
50 | 95075E992468253F0079BF98 /* Products */ = {
51 | isa = PBXGroup;
52 | children = (
53 | 95075E982468253F0079BF98 /* FaceIDAuthentication.app */,
54 | );
55 | name = Products;
56 | sourceTree = "";
57 | };
58 | 95075E9A2468253F0079BF98 /* FaceIDAuthentication */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 95075E9B2468253F0079BF98 /* AppDelegate.swift */,
62 | 95075E9D2468253F0079BF98 /* SceneDelegate.swift */,
63 | 95075E9F2468253F0079BF98 /* ViewController.swift */,
64 | 0186D15F247905E40093C08D /* BiometricIDAuth.swift */,
65 | 95075EA12468253F0079BF98 /* Main.storyboard */,
66 | 95075EA42468254D0079BF98 /* Assets.xcassets */,
67 | 95075EA62468254D0079BF98 /* LaunchScreen.storyboard */,
68 | 95075EA92468254D0079BF98 /* Info.plist */,
69 | );
70 | path = FaceIDAuthentication;
71 | sourceTree = "";
72 | };
73 | /* End PBXGroup section */
74 |
75 | /* Begin PBXNativeTarget section */
76 | 95075E972468253F0079BF98 /* FaceIDAuthentication */ = {
77 | isa = PBXNativeTarget;
78 | buildConfigurationList = 95075EAC2468254D0079BF98 /* Build configuration list for PBXNativeTarget "FaceIDAuthentication" */;
79 | buildPhases = (
80 | 95075E942468253F0079BF98 /* Sources */,
81 | 95075E952468253F0079BF98 /* Frameworks */,
82 | 95075E962468253F0079BF98 /* Resources */,
83 | );
84 | buildRules = (
85 | );
86 | dependencies = (
87 | );
88 | name = FaceIDAuthentication;
89 | productName = FaceIDAuthentication;
90 | productReference = 95075E982468253F0079BF98 /* FaceIDAuthentication.app */;
91 | productType = "com.apple.product-type.application";
92 | };
93 | /* End PBXNativeTarget section */
94 |
95 | /* Begin PBXProject section */
96 | 95075E902468253F0079BF98 /* Project object */ = {
97 | isa = PBXProject;
98 | attributes = {
99 | LastSwiftUpdateCheck = 1120;
100 | LastUpgradeCheck = 1120;
101 | ORGANIZATIONNAME = "Shahrukh Alam";
102 | TargetAttributes = {
103 | 95075E972468253F0079BF98 = {
104 | CreatedOnToolsVersion = 11.2.1;
105 | };
106 | };
107 | };
108 | buildConfigurationList = 95075E932468253F0079BF98 /* Build configuration list for PBXProject "FaceIDAuthentication" */;
109 | compatibilityVersion = "Xcode 9.3";
110 | developmentRegion = en;
111 | hasScannedForEncodings = 0;
112 | knownRegions = (
113 | en,
114 | Base,
115 | );
116 | mainGroup = 95075E8F2468253F0079BF98;
117 | productRefGroup = 95075E992468253F0079BF98 /* Products */;
118 | projectDirPath = "";
119 | projectRoot = "";
120 | targets = (
121 | 95075E972468253F0079BF98 /* FaceIDAuthentication */,
122 | );
123 | };
124 | /* End PBXProject section */
125 |
126 | /* Begin PBXResourcesBuildPhase section */
127 | 95075E962468253F0079BF98 /* Resources */ = {
128 | isa = PBXResourcesBuildPhase;
129 | buildActionMask = 2147483647;
130 | files = (
131 | 95075EA82468254D0079BF98 /* LaunchScreen.storyboard in Resources */,
132 | 95075EA52468254D0079BF98 /* Assets.xcassets in Resources */,
133 | 95075EA32468253F0079BF98 /* Main.storyboard in Resources */,
134 | );
135 | runOnlyForDeploymentPostprocessing = 0;
136 | };
137 | /* End PBXResourcesBuildPhase section */
138 |
139 | /* Begin PBXSourcesBuildPhase section */
140 | 95075E942468253F0079BF98 /* Sources */ = {
141 | isa = PBXSourcesBuildPhase;
142 | buildActionMask = 2147483647;
143 | files = (
144 | 95075EA02468253F0079BF98 /* ViewController.swift in Sources */,
145 | 0186D160247905E40093C08D /* BiometricIDAuth.swift in Sources */,
146 | 95075E9C2468253F0079BF98 /* AppDelegate.swift in Sources */,
147 | 95075E9E2468253F0079BF98 /* SceneDelegate.swift in Sources */,
148 | );
149 | runOnlyForDeploymentPostprocessing = 0;
150 | };
151 | /* End PBXSourcesBuildPhase section */
152 |
153 | /* Begin PBXVariantGroup section */
154 | 95075EA12468253F0079BF98 /* Main.storyboard */ = {
155 | isa = PBXVariantGroup;
156 | children = (
157 | 95075EA22468253F0079BF98 /* Base */,
158 | );
159 | name = Main.storyboard;
160 | sourceTree = "";
161 | };
162 | 95075EA62468254D0079BF98 /* LaunchScreen.storyboard */ = {
163 | isa = PBXVariantGroup;
164 | children = (
165 | 95075EA72468254D0079BF98 /* Base */,
166 | );
167 | name = LaunchScreen.storyboard;
168 | sourceTree = "";
169 | };
170 | /* End PBXVariantGroup section */
171 |
172 | /* Begin XCBuildConfiguration section */
173 | 95075EAA2468254D0079BF98 /* Debug */ = {
174 | isa = XCBuildConfiguration;
175 | buildSettings = {
176 | ALWAYS_SEARCH_USER_PATHS = NO;
177 | CLANG_ANALYZER_NONNULL = YES;
178 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
179 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
180 | CLANG_CXX_LIBRARY = "libc++";
181 | CLANG_ENABLE_MODULES = YES;
182 | CLANG_ENABLE_OBJC_ARC = YES;
183 | CLANG_ENABLE_OBJC_WEAK = YES;
184 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
185 | CLANG_WARN_BOOL_CONVERSION = YES;
186 | CLANG_WARN_COMMA = YES;
187 | CLANG_WARN_CONSTANT_CONVERSION = YES;
188 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
189 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
190 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
191 | CLANG_WARN_EMPTY_BODY = YES;
192 | CLANG_WARN_ENUM_CONVERSION = YES;
193 | CLANG_WARN_INFINITE_RECURSION = YES;
194 | CLANG_WARN_INT_CONVERSION = YES;
195 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
196 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
197 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
198 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
199 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
200 | CLANG_WARN_STRICT_PROTOTYPES = YES;
201 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
202 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
203 | CLANG_WARN_UNREACHABLE_CODE = YES;
204 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
205 | COPY_PHASE_STRIP = NO;
206 | DEBUG_INFORMATION_FORMAT = dwarf;
207 | ENABLE_STRICT_OBJC_MSGSEND = YES;
208 | ENABLE_TESTABILITY = YES;
209 | GCC_C_LANGUAGE_STANDARD = gnu11;
210 | GCC_DYNAMIC_NO_PIC = NO;
211 | GCC_NO_COMMON_BLOCKS = YES;
212 | GCC_OPTIMIZATION_LEVEL = 0;
213 | GCC_PREPROCESSOR_DEFINITIONS = (
214 | "DEBUG=1",
215 | "$(inherited)",
216 | );
217 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
218 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
219 | GCC_WARN_UNDECLARED_SELECTOR = YES;
220 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
221 | GCC_WARN_UNUSED_FUNCTION = YES;
222 | GCC_WARN_UNUSED_VARIABLE = YES;
223 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
224 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
225 | MTL_FAST_MATH = YES;
226 | ONLY_ACTIVE_ARCH = YES;
227 | SDKROOT = iphoneos;
228 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
229 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
230 | };
231 | name = Debug;
232 | };
233 | 95075EAB2468254D0079BF98 /* Release */ = {
234 | isa = XCBuildConfiguration;
235 | buildSettings = {
236 | ALWAYS_SEARCH_USER_PATHS = NO;
237 | CLANG_ANALYZER_NONNULL = YES;
238 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
240 | CLANG_CXX_LIBRARY = "libc++";
241 | CLANG_ENABLE_MODULES = YES;
242 | CLANG_ENABLE_OBJC_ARC = YES;
243 | CLANG_ENABLE_OBJC_WEAK = YES;
244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
245 | CLANG_WARN_BOOL_CONVERSION = YES;
246 | CLANG_WARN_COMMA = YES;
247 | CLANG_WARN_CONSTANT_CONVERSION = YES;
248 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
249 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
250 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
251 | CLANG_WARN_EMPTY_BODY = YES;
252 | CLANG_WARN_ENUM_CONVERSION = YES;
253 | CLANG_WARN_INFINITE_RECURSION = YES;
254 | CLANG_WARN_INT_CONVERSION = YES;
255 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
256 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
257 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
258 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
259 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
260 | CLANG_WARN_STRICT_PROTOTYPES = YES;
261 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
262 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
263 | CLANG_WARN_UNREACHABLE_CODE = YES;
264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
265 | COPY_PHASE_STRIP = NO;
266 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
267 | ENABLE_NS_ASSERTIONS = NO;
268 | ENABLE_STRICT_OBJC_MSGSEND = YES;
269 | GCC_C_LANGUAGE_STANDARD = gnu11;
270 | GCC_NO_COMMON_BLOCKS = YES;
271 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
272 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
273 | GCC_WARN_UNDECLARED_SELECTOR = YES;
274 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
275 | GCC_WARN_UNUSED_FUNCTION = YES;
276 | GCC_WARN_UNUSED_VARIABLE = YES;
277 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
278 | MTL_ENABLE_DEBUG_INFO = NO;
279 | MTL_FAST_MATH = YES;
280 | SDKROOT = iphoneos;
281 | SWIFT_COMPILATION_MODE = wholemodule;
282 | SWIFT_OPTIMIZATION_LEVEL = "-O";
283 | VALIDATE_PRODUCT = YES;
284 | };
285 | name = Release;
286 | };
287 | 95075EAD2468254D0079BF98 /* Debug */ = {
288 | isa = XCBuildConfiguration;
289 | buildSettings = {
290 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
291 | CODE_SIGN_STYLE = Automatic;
292 | DEVELOPMENT_TEAM = 565GS4VPDB;
293 | INFOPLIST_FILE = FaceIDAuthentication/Info.plist;
294 | LD_RUNPATH_SEARCH_PATHS = (
295 | "$(inherited)",
296 | "@executable_path/Frameworks",
297 | );
298 | PRODUCT_BUNDLE_IDENTIFIER = com.Shahrukh.FaceIDAuthentication;
299 | PRODUCT_NAME = "$(TARGET_NAME)";
300 | SWIFT_VERSION = 5.0;
301 | TARGETED_DEVICE_FAMILY = "1,2";
302 | };
303 | name = Debug;
304 | };
305 | 95075EAE2468254D0079BF98 /* Release */ = {
306 | isa = XCBuildConfiguration;
307 | buildSettings = {
308 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
309 | CODE_SIGN_STYLE = Automatic;
310 | DEVELOPMENT_TEAM = 565GS4VPDB;
311 | INFOPLIST_FILE = FaceIDAuthentication/Info.plist;
312 | LD_RUNPATH_SEARCH_PATHS = (
313 | "$(inherited)",
314 | "@executable_path/Frameworks",
315 | );
316 | PRODUCT_BUNDLE_IDENTIFIER = com.Shahrukh.FaceIDAuthentication;
317 | PRODUCT_NAME = "$(TARGET_NAME)";
318 | SWIFT_VERSION = 5.0;
319 | TARGETED_DEVICE_FAMILY = "1,2";
320 | };
321 | name = Release;
322 | };
323 | /* End XCBuildConfiguration section */
324 |
325 | /* Begin XCConfigurationList section */
326 | 95075E932468253F0079BF98 /* Build configuration list for PBXProject "FaceIDAuthentication" */ = {
327 | isa = XCConfigurationList;
328 | buildConfigurations = (
329 | 95075EAA2468254D0079BF98 /* Debug */,
330 | 95075EAB2468254D0079BF98 /* Release */,
331 | );
332 | defaultConfigurationIsVisible = 0;
333 | defaultConfigurationName = Release;
334 | };
335 | 95075EAC2468254D0079BF98 /* Build configuration list for PBXNativeTarget "FaceIDAuthentication" */ = {
336 | isa = XCConfigurationList;
337 | buildConfigurations = (
338 | 95075EAD2468254D0079BF98 /* Debug */,
339 | 95075EAE2468254D0079BF98 /* Release */,
340 | );
341 | defaultConfigurationIsVisible = 0;
342 | defaultConfigurationName = Release;
343 | };
344 | /* End XCConfigurationList section */
345 | };
346 | rootObject = 95075E902468253F0079BF98 /* Project object */;
347 | }
348 |
--------------------------------------------------------------------------------