[
  {
    "path": ".gitignore",
    "content": "# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n## Build generated\nbuild/\nDerivedData/\n\n## Various settings\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata/\n\n## Other\n*.moved-aside\n*.xccheckout\n*.xcscmblueprint\n\n## Obj-C/Swift specific\n*.hmap\n*.ipa\n*.dSYM.zip\n*.dSYM\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# Pods/\n\n# Carthage\n#\n# Add this line if you want to avoid checking in source code from Carthage dependencies.\n# Carthage/Checkouts\n\nCarthage/Build\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the\n# screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://docs.fastlane.tools/best-practices/source-control/#source-control\n\nfastlane/report.xml\nfastlane/Preview.html\nfastlane/screenshots\nfastlane/test_output\n\n# Code Injection\n#\n# After new code Injection tools there's a generated folder /iOSInjectionProject\n# https://github.com/johnno1962/injectionforxcode\n\niOSInjectionProject/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: objective-c\nosx_image: xcode10\nxcode_project: YZAuthID.xcodeproj\nxcode_scheme: YZAuthID\n\nbefore_install:\n- env\n- xcodebuild -version\n- xcodebuild -showsdks\n- xcpretty --version\n\nscript:\n- set -o pipefail\n- xcodebuild clean build -project \"$TRAVIS_XCODE_PROJECT\" -scheme \"$TRAVIS_XCODE_SCHEME\" -sdk iphonesimulator PLATFORM_NAME=iphonesimulator -configuration Debug | xcpretty -c\n"
  },
  {
    "path": "ExportOptions.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>compileBitcode</key>\n\t<false/>\n\t<key>method</key>\n\t<string>development</string>\n</dict>\n</plist>"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Yanzheng\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# YZAuthID\n\n[![Build Status](https://travis-ci.org/micyo202/YZAuthID.svg)](https://travis-ci.org/micyo202/YZAuthID)\n[![Version](https://img.shields.io/badge/version-2.1.0-yellow.svg)](https://github.com/micyo202/YZAuthID)\n[![Cocoapods](https://img.shields.io/badge/pod-1.10.0-green.svg)](https://cocoapods.org/?q=YZAuthID)\n[![Platform](https://img.shields.io/badge/platform-ios-red.svg)](https://github.com/micyo202/YZAuthID)\n[![License MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://github.com/micyo202/YZAuthID/blob/master/LICENSE)\n[![GitHub stars](https://img.shields.io/github/stars/micyo202/YZAuthID.svg?style=social&label=Stars)](https://github.com/micyo202/YZAuthID)\n[![GitHub forks](https://img.shields.io/github/forks/micyo202/YZAuthID.svg?style=social&label=Fork)](https://github.com/micyo202/YZAuthID)\n\n仅需一个回调方法即可轻松实现iOS TouchID（指纹）/ FaceID（面容）验证功能，代码简洁易懂。\n\n#### 详细使用方法及介绍请参考[简书](https://www.jianshu.com/p/da752036b2f4)\n\n#### 实例效果图：\n\n<img src=\"https://github.com/micyo202/YZAuthID/raw/master/auth_finger_1.png\" alt=\"指纹1\" title=\"指纹界面\">\n\n<img src=\"https://github.com/micyo202/YZAuthID/raw/master/auth_finger_2.png\" alt=\"指纹2\" title=\"开始认证\">\n\n<img src=\"https://github.com/micyo202/YZAuthID/raw/master/auth_finger_3.png\" alt=\"指纹3\" title=\"认证失败\">\n\n<img src=\"https://github.com/micyo202/YZAuthID/raw/master/auth_face_1.png\" alt=\"面容1\" title=\"面容界面\">\n\n<img src=\"https://github.com/micyo202/YZAuthID/raw/master/auth_face_2.png\" alt=\"面容2\" title=\"开始认证\">\n\n<img src=\"https://github.com/micyo202/YZAuthID/raw/master/auth_face_3.png\" alt=\"面容3\" title=\"认证失败\">\n"
  },
  {
    "path": "Supporting Files/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  YZAuthID\n//\n//  Created by Apple on 2018/07/26.\n//  Copyright © 2018年 Yanzheng. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n\n@end\n\n"
  },
  {
    "path": "Supporting Files/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  YZAuthID\n//\n//  Created by Apple on 2018/07/26.\n//  Copyright © 2018年 Yanzheng. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n\n@interface AppDelegate ()\n\n@end\n\n@implementation AppDelegate\n\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    // Override point for customization after application launch.\n    \n    // 设置顶部状态栏字体为白色\n    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;\n    \n    return YES;\n}\n\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.\n}\n\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n}\n\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.\n}\n\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n}\n\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n}\n\n\n@end\n"
  },
  {
    "path": "Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"83.5x83.5\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ios-marketing\",\n      \"size\" : \"1024x1024\",\n      \"scale\" : \"1x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Supporting Files/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"13122.16\" systemVersion=\"17A277\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"13104.12\"/>\n        <capability name=\"Safe area layout guides\" minToolsVersion=\"9.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <viewLayoutGuide key=\"safeArea\" id=\"6Tk-OE-BBY\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Supporting Files/Images.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Supporting Files/Images.xcassets/auth_face.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"auth_face@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Supporting Files/Images.xcassets/auth_finger.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"auth_finger@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Supporting Files/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSFaceIDUsageDescription</key>\n\t<string>允许设备访问Face ID</string>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Supporting Files/main.m",
    "content": "//\n//  main.m\n//  YZAuthID\n//\n//  Created by Apple on 2018/07/26.\n//  Copyright © 2018年 Yanzheng. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n    @autoreleasepool {\n        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n    }\n}\n"
  },
  {
    "path": "YZAuthID/YZAuthID.h",
    "content": "/************************************************************\n Class    : YZAuthID.h\n Describe : TouchID/FaceID 认证方法\n Company  : Micyo\n Author   : Yanzheng\n Date     : 2018-07-26\n Version  : 2.0\n Declare  : Copyright © 2018 Yanzheng. All rights reserved.\n ************************************************************/\n\n#import <LocalAuthentication/LocalAuthentication.h>\n\n/**\n *  TouchID/FaceID 状态\n */\ntypedef NS_ENUM(NSUInteger, YZAuthIDState){\n    \n    /**\n     *  当前设备不支持TouchID/FaceID\n     */\n    YZAuthIDStateNotSupport = 0,\n    /**\n     *  TouchID/FaceID 验证成功\n     */\n    YZAuthIDStateSuccess = 1,\n    \n    /**\n     *  TouchID/FaceID 验证失败\n     */\n    YZAuthIDStateFail = 2,\n    /**\n     *  TouchID/FaceID 被用户手动取消\n     */\n    YZAuthIDStateUserCancel = 3,\n    /**\n     *  用户不使用TouchID/FaceID,选择手动输入密码\n     */\n    YZAuthIDStateInputPassword = 4,\n    /**\n     *  TouchID/FaceID 被系统取消 (如遇到来电,锁屏,按了Home键等)\n     */\n    YZAuthIDStateSystemCancel = 5,\n    /**\n     *  TouchID/FaceID 无法启动,因为用户没有设置密码\n     */\n    YZAuthIDStatePasswordNotSet = 6,\n    /**\n     *  TouchID/FaceID 无法启动,因为用户没有设置TouchID/FaceID\n     */\n    YZAuthIDStateTouchIDNotSet = 7,\n    /**\n     *  TouchID/FaceID 无效\n     */\n    YZAuthIDStateTouchIDNotAvailable = 8,\n    /**\n     *  TouchID/FaceID 被锁定(连续多次验证TouchID/FaceID失败,系统需要用户手动输入密码)\n     */\n    YZAuthIDStateTouchIDLockout = 9,\n    /**\n     *  当前软件被挂起并取消了授权 (如App进入了后台等)\n     */\n    YZAuthIDStateAppCancel = 10,\n    /**\n     *  当前软件被挂起并取消了授权 (LAContext对象无效)\n     */\n    YZAuthIDStateInvalidContext = 11,\n    /**\n     *  系统版本不支持TouchID/FaceID (必须高于iOS 8.0才能使用)\n     */\n    YZAuthIDStateVersionNotSupport = 12\n};\n\n\n@interface YZAuthID : LAContext\n\ntypedef void (^YZAuthIDStateBlock)(YZAuthIDState state, NSError *error);\n\n/**\n * 启动TouchID/FaceID进行验证\n * @param describe TouchID/FaceID显示的描述\n * @param block 回调状态的block\n */\n- (void)yz_showAuthIDWithDescribe:(NSString *)describe block:(YZAuthIDStateBlock)block;\n\n@end\n"
  },
  {
    "path": "YZAuthID/YZAuthID.m",
    "content": "/************************************************************\n Class    : YZAuthID.m\n Describe : TouchID/FaceID 认证方法\n Company  : Micyo\n Author   : Yanzheng\n Date     : 2018-07-26\n Version  : 2.0\n Declare  : Copyright © 2018 Yanzheng. All rights reserved.\n ************************************************************/\n\n#import \"YZAuthID.h\"\n#import <UIKit/UIKit.h>\n\n#define iPhoneX (UIScreen.mainScreen.bounds.size.width >= 375.f && UIScreen.mainScreen.bounds.size.height >= 812.f)\n\n@implementation YZAuthID\n\n+ (instancetype)sharedInstance {\n    static YZAuthID *instance = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        instance = [[YZAuthID alloc] init];\n    });\n    return instance;\n}\n\n- (void)yz_showAuthIDWithDescribe:(NSString *)describe block:(YZAuthIDStateBlock)block {\n    if(!describe) {\n        if(iPhoneX){\n            describe = @\"验证已有面容\";\n        }else{\n            describe = @\"通过Home键验证已有指纹\";\n        }\n    }\n    \n    if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0) {\n        \n        dispatch_async(dispatch_get_main_queue(), ^{\n            NSLog(@\"系统版本不支持TouchID/FaceID (必须高于iOS 8.0才能使用)\");\n            block(YZAuthIDStateVersionNotSupport, nil);\n        });\n        \n        return;\n    }\n    \n    LAContext *context = [[LAContext alloc] init];\n    \n    // 认证失败提示信息，为 @\"\" 则不提示\n    context.localizedFallbackTitle = @\"输入密码\";\n    \n    NSError *error = nil;\n    \n    // LAPolicyDeviceOwnerAuthenticationWithBiometrics: 用TouchID/FaceID验证\n    // LAPolicyDeviceOwnerAuthentication: 用TouchID/FaceID或密码验证, 默认是错误两次或锁定后, 弹出输入密码界面（本案例使用）\n    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]) {\n        [context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:describe reply:^(BOOL success, NSError * _Nullable error) {\n            \n            if (success) {\n                dispatch_async(dispatch_get_main_queue(), ^{\n                    NSLog(@\"TouchID/FaceID 验证成功\");\n                    block(YZAuthIDStateSuccess, error);\n                });\n            }else if(error){\n                \n                if (@available(iOS 11.0, *)) {\n                    switch (error.code) {\n                        case LAErrorAuthenticationFailed:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID/FaceID 验证失败\");\n                                block(YZAuthIDStateFail, error);\n                            });\n                            break;\n                        }\n                        case LAErrorUserCancel:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID/FaceID 被用户手动取消\");\n                                block(YZAuthIDStateUserCancel, error);\n                            });\n                        }\n                            break;\n                        case LAErrorUserFallback:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"用户不使用TouchID/FaceID,选择手动输入密码\");\n                                block(YZAuthIDStateInputPassword, error);\n                            });\n                        }\n                            break;\n                        case LAErrorSystemCancel:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID/FaceID 被系统取消 (如遇到来电,锁屏,按了Home键等)\");\n                                block(YZAuthIDStateSystemCancel, error);\n                            });\n                        }\n                            break;\n                        case LAErrorPasscodeNotSet:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID/FaceID 无法启动,因为用户没有设置密码\");\n                                block(YZAuthIDStatePasswordNotSet, error);\n                            });\n                        }\n                            break;\n                            //case LAErrorTouchIDNotEnrolled:{\n                        case LAErrorBiometryNotEnrolled:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID/FaceID 无法启动,因为用户没有设置TouchID/FaceID\");\n                                block(YZAuthIDStateTouchIDNotSet, error);\n                            });\n                        }\n                            break;\n                            //case LAErrorTouchIDNotAvailable:{\n                        case LAErrorBiometryNotAvailable:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID/FaceID 无效\");\n                                block(YZAuthIDStateTouchIDNotAvailable, error);\n                            });\n                        }\n                            break;\n                            //case LAErrorTouchIDLockout:{\n                        case LAErrorBiometryLockout:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID/FaceID 被锁定(连续多次验证TouchID/FaceID失败,系统需要用户手动输入密码)\");\n                                block(YZAuthIDStateTouchIDLockout, error);\n                            });\n                        }\n                            break;\n                        case LAErrorAppCancel:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"当前软件被挂起并取消了授权 (如App进入了后台等)\");\n                                block(YZAuthIDStateAppCancel, error);\n                            });\n                        }\n                            break;\n                        case LAErrorInvalidContext:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"当前软件被挂起并取消了授权 (LAContext对象无效)\");\n                                block(YZAuthIDStateInvalidContext, error);\n                            });\n                        }\n                            break;\n                        default:\n                            break;\n                    }\n                } else {\n                    // iOS 11.0以下的版本只有 TouchID 认证\n                    switch (error.code) {\n                        case LAErrorAuthenticationFailed:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID 验证失败\");\n                                block(YZAuthIDStateFail, error);\n                            });\n                            break;\n                        }\n                        case LAErrorUserCancel:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID 被用户手动取消\");\n                                block(YZAuthIDStateUserCancel, error);\n                            });\n                        }\n                            break;\n                        case LAErrorUserFallback:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"用户不使用TouchID,选择手动输入密码\");\n                                block(YZAuthIDStateInputPassword, error);\n                            });\n                        }\n                            break;\n                        case LAErrorSystemCancel:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID 被系统取消 (如遇到来电,锁屏,按了Home键等)\");\n                                block(YZAuthIDStateSystemCancel, error);\n                            });\n                        }\n                            break;\n                        case LAErrorPasscodeNotSet:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID 无法启动,因为用户没有设置密码\");\n                                block(YZAuthIDStatePasswordNotSet, error);\n                            });\n                        }\n                            break;\n                        case LAErrorBiometryNotEnrolled:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID 无法启动,因为用户没有设置TouchID\");\n                                block(YZAuthIDStateTouchIDNotSet, error);\n                            });\n                        }\n                            break;\n                            //case :{\n                        case LAErrorBiometryNotAvailable:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID 无效\");\n                                block(YZAuthIDStateTouchIDNotAvailable, error);\n                            });\n                        }\n                            break;\n                        case LAErrorBiometryLockout:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"TouchID 被锁定(连续多次验证TouchID失败,系统需要用户手动输入密码)\");\n                                block(YZAuthIDStateTouchIDLockout, error);\n                            });\n                        }\n                            break;\n                        case LAErrorAppCancel:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"当前软件被挂起并取消了授权 (如App进入了后台等)\");\n                                block(YZAuthIDStateAppCancel, error);\n                            });\n                        }\n                            break;\n                        case LAErrorInvalidContext:{\n                            dispatch_async(dispatch_get_main_queue(), ^{\n                                NSLog(@\"当前软件被挂起并取消了授权 (LAContext对象无效)\");\n                                block(YZAuthIDStateInvalidContext, error);\n                            });\n                        }\n                            break;\n                        default:\n                            break;\n                    }\n                }\n                \n            }\n        }];\n        \n    }else{\n        \n        dispatch_async(dispatch_get_main_queue(), ^{\n            NSLog(@\"当前设备不支持TouchID/FaceID\");\n            block(YZAuthIDStateNotSupport, error);\n        });\n        \n    }\n}\n\n@end\n"
  },
  {
    "path": "YZAuthID.podspec",
    "content": "Pod::Spec.new do |s|\n    s.name         = 'YZAuthID'\n    s.version      = '2.1.0'\n    s.summary      = 'TouchID/FaceID auth.'\n    s.homepage     = 'https://github.com/micyo202/YZAuthID'\n    s.license      = { :type => 'MIT', :file => 'LICENSE' }\n    s.authors      = {'Yanzheng' => 'micyo202@163.com'}\n    s.platform     = :ios, '12.0'\n    s.ios.deployment_target = '12.0'\n    s.source       = {:git => 'https://github.com/micyo202/YZAuthID.git', :tag => s.version}\n    s.source_files = 'YZAuthID/**/*.{h,m}'\n    s.requires_arc = true\nend\n"
  },
  {
    "path": "YZAuthID.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 48;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t182B79E31FECDBAF005E0E81 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79E21FECDBAF005E0E81 /* AppDelegate.m */; };\n\t\t182B79E61FECDBAF005E0E81 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79E51FECDBAF005E0E81 /* ViewController.m */; };\n\t\t182B79E91FECDBAF005E0E81 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 182B79E71FECDBAF005E0E81 /* Main.storyboard */; };\n\t\t182B79EB1FECDBAF005E0E81 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 182B79EA1FECDBAF005E0E81 /* Assets.xcassets */; };\n\t\t182B79EE1FECDBAF005E0E81 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 182B79EC1FECDBAF005E0E81 /* LaunchScreen.storyboard */; };\n\t\t182B79F11FECDBAF005E0E81 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79F01FECDBAF005E0E81 /* main.m */; };\n\t\t182B79FC1FECDCDB005E0E81 /* YZAuthID.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79FB1FECDCDB005E0E81 /* YZAuthID.m */; };\n\t\t182B79FE1FECEE5A005E0E81 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 182B79FD1FECEE5A005E0E81 /* Images.xcassets */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t182B79DE1FECDBAF005E0E81 /* YZAuthID.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YZAuthID.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t182B79E11FECDBAF005E0E81 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t182B79E21FECDBAF005E0E81 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t182B79E41FECDBAF005E0E81 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = \"<group>\"; };\n\t\t182B79E51FECDBAF005E0E81 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = \"<group>\"; };\n\t\t182B79E81FECDBAF005E0E81 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t182B79EA1FECDBAF005E0E81 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t182B79ED1FECDBAF005E0E81 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t182B79EF1FECDBAF005E0E81 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t182B79F01FECDBAF005E0E81 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t182B79FA1FECDCDB005E0E81 /* YZAuthID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YZAuthID.h; sourceTree = \"<group>\"; };\n\t\t182B79FB1FECDCDB005E0E81 /* YZAuthID.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YZAuthID.m; sourceTree = \"<group>\"; };\n\t\t182B79FD1FECEE5A005E0E81 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t182B79DB1FECDBAF005E0E81 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t182B79D51FECDBAF005E0E81 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t182B79F91FECDBF6005E0E81 /* Supporting Files */,\n\t\t\t\t182B79F71FECDBD6005E0E81 /* YZAuthIDDemo */,\n\t\t\t\t182B79E01FECDBAF005E0E81 /* YZAuthID */,\n\t\t\t\t182B79DF1FECDBAF005E0E81 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t182B79DF1FECDBAF005E0E81 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t182B79DE1FECDBAF005E0E81 /* YZAuthID.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t182B79E01FECDBAF005E0E81 /* YZAuthID */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t182B79FA1FECDCDB005E0E81 /* YZAuthID.h */,\n\t\t\t\t182B79FB1FECDCDB005E0E81 /* YZAuthID.m */,\n\t\t\t);\n\t\t\tpath = YZAuthID;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t182B79F71FECDBD6005E0E81 /* YZAuthIDDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t182B79E41FECDBAF005E0E81 /* ViewController.h */,\n\t\t\t\t182B79E51FECDBAF005E0E81 /* ViewController.m */,\n\t\t\t\t182B79E71FECDBAF005E0E81 /* Main.storyboard */,\n\t\t\t);\n\t\t\tpath = YZAuthIDDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t182B79F91FECDBF6005E0E81 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t182B79E11FECDBAF005E0E81 /* AppDelegate.h */,\n\t\t\t\t182B79E21FECDBAF005E0E81 /* AppDelegate.m */,\n\t\t\t\t182B79EA1FECDBAF005E0E81 /* Assets.xcassets */,\n\t\t\t\t182B79EC1FECDBAF005E0E81 /* LaunchScreen.storyboard */,\n\t\t\t\t182B79EF1FECDBAF005E0E81 /* Info.plist */,\n\t\t\t\t182B79F01FECDBAF005E0E81 /* main.m */,\n\t\t\t\t182B79FD1FECEE5A005E0E81 /* Images.xcassets */,\n\t\t\t);\n\t\t\tpath = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t182B79DD1FECDBAF005E0E81 /* YZAuthID */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 182B79F41FECDBAF005E0E81 /* Build configuration list for PBXNativeTarget \"YZAuthID\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t182B79DA1FECDBAF005E0E81 /* Sources */,\n\t\t\t\t182B79DB1FECDBAF005E0E81 /* Frameworks */,\n\t\t\t\t182B79DC1FECDBAF005E0E81 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = YZAuthID;\n\t\t\tproductName = YZAuthID;\n\t\t\tproductReference = 182B79DE1FECDBAF005E0E81 /* YZAuthID.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t182B79D61FECDBAF005E0E81 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0920;\n\t\t\t\tORGANIZATIONNAME = Yanzheng;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t182B79DD1FECDBAF005E0E81 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 9.2;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 182B79D91FECDBAF005E0E81 /* Build configuration list for PBXProject \"YZAuthID\" */;\n\t\t\tcompatibilityVersion = \"Xcode 8.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 182B79D51FECDBAF005E0E81;\n\t\t\tproductRefGroup = 182B79DF1FECDBAF005E0E81 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t182B79DD1FECDBAF005E0E81 /* YZAuthID */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t182B79DC1FECDBAF005E0E81 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t182B79EE1FECDBAF005E0E81 /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t182B79FE1FECEE5A005E0E81 /* Images.xcassets in Resources */,\n\t\t\t\t182B79EB1FECDBAF005E0E81 /* Assets.xcassets in Resources */,\n\t\t\t\t182B79E91FECDBAF005E0E81 /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t182B79DA1FECDBAF005E0E81 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t182B79E61FECDBAF005E0E81 /* ViewController.m in Sources */,\n\t\t\t\t182B79F11FECDBAF005E0E81 /* main.m in Sources */,\n\t\t\t\t182B79E31FECDBAF005E0E81 /* AppDelegate.m in Sources */,\n\t\t\t\t182B79FC1FECDCDB005E0E81 /* YZAuthID.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t182B79E71FECDBAF005E0E81 /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t182B79E81FECDBAF005E0E81 /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t182B79EC1FECDBAF005E0E81 /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t182B79ED1FECDBAF005E0E81 /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t182B79F21FECDBAF005E0E81 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 12.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t182B79F31FECDBAF005E0E81 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 12.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t182B79F51FECDBAF005E0E81 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEVELOPMENT_TEAM = YPP9C225DR;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/Supporting Files/Info.plist\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 12.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tMARKETING_VERSION = 2.1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.yan.YZAuthID;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t182B79F61FECDBAF005E0E81 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEVELOPMENT_TEAM = YPP9C225DR;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/Supporting Files/Info.plist\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 12.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tMARKETING_VERSION = 2.1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.yan.YZAuthID;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t182B79D91FECDBAF005E0E81 /* Build configuration list for PBXProject \"YZAuthID\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t182B79F21FECDBAF005E0E81 /* Debug */,\n\t\t\t\t182B79F31FECDBAF005E0E81 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t182B79F41FECDBAF005E0E81 /* Build configuration list for PBXNativeTarget \"YZAuthID\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t182B79F51FECDBAF005E0E81 /* Debug */,\n\t\t\t\t182B79F61FECDBAF005E0E81 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 182B79D61FECDBAF005E0E81 /* Project object */;\n}\n"
  },
  {
    "path": "YZAuthID.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:YZAuthID.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "YZAuthID.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "YZAuthIDDemo/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"13771\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"13772\"/>\n        <capability name=\"Safe area layout guides\" minToolsVersion=\"9.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"ViewController\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <viewLayoutGuide key=\"safeArea\" id=\"6Tk-OE-BBY\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "YZAuthIDDemo/ViewController.h",
    "content": "/************************************************************\n Class    : ViewController.h\n Describe : YZAuthID 认证方法示例代码\n Company  : Micyo\n Author   : Yanzheng\n Date     : 2018-07-26\n Version  : 2.0\n Declare  : Copyright © 2018 Yanzheng. All rights reserved.\n ************************************************************/\n\n#import <UIKit/UIKit.h>\n\n@interface ViewController : UIViewController\n\n\n@end\n\n"
  },
  {
    "path": "YZAuthIDDemo/ViewController.m",
    "content": "/************************************************************\n Class    : ViewController.m\n Describe : YZAuthID 认证方法示例代码\n Company  : Micyo\n Author   : Yanzheng\n Date     : 2018-07-26\n Version  : 2.0\n Declare  : Copyright © 2018 Yanzheng. All rights reserved.\n ************************************************************/\n\n#import \"ViewController.h\"\n#import \"YZAuthID.h\"\n\n#define iPhoneX (UIScreen.mainScreen.bounds.size.width == 375.f && UIScreen.mainScreen.bounds.size.height == 812.f)\n\n@interface ViewController ()\n\n@property (nonatomic, strong) UILabel *hintLabel;           // 提示标题\n@property (nonatomic, strong) UIImageView *imageView;       // 图标\n@property (nonatomic, strong) UIButton *actionBtn;          // 按钮\n\n@property (nonatomic, copy) NSString *authImage;            // 认证图标名\n@property (nonatomic, copy) NSString *authName;             // 认证名称\n\n@end\n\n@implementation ViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    // Do any additional setup after loading the view, typically from a nib.\n    \n    self.view.backgroundColor = UIColor.whiteColor;\n    \n    [self initialize];\n}\n\n#pragma mark - 初始化方法\n- (void)initialize {\n    // 设置值\n    if(iPhoneX){\n        self.authImage = @\"auth_face\";\n        self.authName = @\"面容\";\n    }else{\n        self.authImage = @\"auth_finger\";\n        self.authName = @\"指纹\";\n    }\n    \n    // 添加组件\n    [self.view addSubview:self.hintLabel];\n    [self.view addSubview:self.imageView];\n    [self.view addSubview:self.actionBtn];\n    \n    // 开始认证\n    [self authVerification];\n}\n\n#pragma mark - 懒加载各组件\n- (UILabel *)hintLabel {\n    if(!_hintLabel){\n        _hintLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 160, self.view.frame.size.width, 60)];\n        _hintLabel.font = [UIFont systemFontOfSize:22.f];\n        _hintLabel.textAlignment = NSTextAlignmentCenter;\n        _hintLabel.numberOfLines = 0;\n        _hintLabel.text = [NSString stringWithFormat:@\"YZAuth\\n验证%@以进行登录\", self.authName];\n    }\n    return _hintLabel;\n}\n\n- (UIImageView *)imageView {\n    if(!_imageView){\n        \n        _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2 - 35, self.hintLabel.frame.origin.y + 130, 70, 70)];\n        _imageView.image = [UIImage imageNamed:self.authImage];\n    }\n    return _imageView;\n}\n\n- (UIButton *)actionBtn {\n    if(!_actionBtn){\n        _actionBtn = [UIButton buttonWithType:UIButtonTypeSystem];\n        _actionBtn.frame = CGRectMake(60, self.imageView.frame.origin.y + 190, self.view.frame.size.width - 120, 40);\n        [_actionBtn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];\n        _actionBtn.titleLabel.font = [UIFont systemFontOfSize:18.f];\n        [_actionBtn setTitle:[NSString stringWithFormat:@\"点击验证%@\", self.authName] forState:UIControlStateNormal];\n        [_actionBtn setBackgroundColor:[UIColor colorWithRed:123/255.f green:188/255.f blue:231/255.f alpha:1]];\n        _actionBtn.layer.cornerRadius = 5.f;\n        _actionBtn.layer.masksToBounds = YES;\n        [_actionBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];\n    }\n    return _actionBtn;\n}\n\n#pragma mark - 按钮点击事件\n- (void)btnClicked:(UIButton *)sender {\n    // 唤起指纹、面容ID验证\n    [self authVerification];\n}\n\n#pragma mark - 验证TouchID/FaceID\n- (void)authVerification {\n    \n    YZAuthID *authID = [[YZAuthID alloc] init];\n    \n    [authID yz_showAuthIDWithDescribe:nil block:^(YZAuthIDState state, NSError *error) {\n        \n        if (state == YZAuthIDStateNotSupport) { // 不支持TouchID/FaceID\n            NSLog(@\"对不起，当前设备不支持指纹/面容ID\");\n        } else if(state == YZAuthIDStateFail) { // 认证失败\n            NSLog(@\"指纹/面容ID不正确，认证失败\");\n        } else if(state == YZAuthIDStateTouchIDLockout) {   // 多次错误，已被锁定\n            NSLog(@\"多次错误，指纹/面容ID已被锁定，请到手机解锁界面输入密码\");\n        } else if (state == YZAuthIDStateSuccess) { // TouchID/FaceID验证成功\n            NSLog(@\"认证成功！\");\n        }\n        \n    }];\n}\n\n- (void)didReceiveMemoryWarning {\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n@end\n"
  },
  {
    "path": "archive.sh",
    "content": "#!/bin/bash\n\n# 打包脚本使用说明：\n# 1.修改：yz_cocopods、yz_project、yz_scheme参数\n# 2.执行：./archive.sh 默认打 Debug 包\n# 3.执行：./archive.sh Release 打 Release 包\n\n# 用Cocopods管理的.xcworkspace项目,赋值true；用Xcode默认创建的.xcodeproj,赋值false\nyz_cocopods=true\n# 工程名称(project的名称)\nyz_project=YZAuthID\n# scheme名称（也就是工程的target名称）\nyz_scheme=YZAuthID\n# Debug Release\nif [ -z $1 ]; then\n\tyz_configuration=Debug\nelse\n\tyz_configuration=$1\nfi\n# method，打包的方式（方式分别为 development, ad-hoc, app-store, enterprise）\nyz_method=development\n# 日期时间\nyz_date=`date +%Y%m%d_%H%M%S`\n# 获取当前脚本所在目录\nyz_script_path=$( cd $( dirname $0 ) && pwd )\n# 工程目录\nyz_project_path=$yz_script_path\n# 指定输出导出文件夹路径\nyz_export_path=$yz_project_path/package/$yz_date\n# 指定输出归档文件路径\nyz_export_archive=$yz_export_path/$yz_scheme.xcarchive\n# 指定输出ipa名称\nyz_export_ipa=$yz_export_path/$yz_scheme.ipa\n# 指定导出ipa包需要用到的plist配置文件的路径\nyz_export_options_plist=$yz_project_path/ExportOptions.plist\n\n#  下面两个参数只是在手动指定Pofile文件的时候用到，如果使用Xcode自动管理Profile,直接留空就好\n# (跟method对应的)mobileprovision文件名，需要先双击安装.mobileprovision文件.手动管理Profile时必填\nyz_mobileprovision_name=\"\"\n# 项目的bundleID，手动管理Profile时必填\nyz_bundle_identifier=\"\"\n\n# 输出参数\necho --------------------脚本配置参数检查--------------------\necho yz_cocopods=$yz_cocopods\necho yz_project=$yz_project\necho yz_scheme=$yz_scheme\necho yz_configuration=$yz_configuration\necho yz_method=$yz_method\necho yz_date=$yz_date\necho yz_script_path=$yz_script_path\necho yz_project_path=$yz_project_path\necho yz_export_path=$yz_export_path\necho yz_export_archive=$yz_export_archive\necho yz_export_ipa=$yz_export_ipa\necho yz_export_options_plist=$yz_export_options_plist\n\nif [[ \"Debug\" != $yz_configuration ]] && [[ \"Release\" != $yz_configuration ]]; then\n\techo \"参数yz_configuration=${1}不正确，yz_configuration取值范围：Debug（默认）、Release\"\n\texit 1\nfi\n\n# 开发打包\necho --------------------自动打包脚本执行--------------------\n\n# 进入项目工程目录\ncd $yz_project_path\n\n# 指定输出文件目录不存在则创建\nif [ -d $yz_export_path ] ; then\n\techo $yz_export_path\nelse\n\tmkdir -pv $yz_export_path\nfi\n\n# 判断是Cocoapods还是Xcode项目\nif $yz_cocoapods ; then\n\necho -------------------Cocoapods 项目打包-------------------\n\n# pods 添加\npod install\n\n# 打包脚本执行\nxcodebuild archive \\\n-workspace $yz_project.xcworkspace \\\n-scheme $yz_scheme \\\n-configuration $yz_configuration \\\n-archivePath $yz_export_archive \\\nclean \\\nbuild\n\nelse\n\necho ---------------------Xcode 项目打包---------------------\n\nxcodebuild archive \\\n-project $yz_project.xcodeproj \\\n-scheme $yz_scheme \\\n-configuration $yz_configuration \\\n-archivePath $yz_export_archive \\\nclean \\\nbuild\n\nfi\n\n# 检查构建是否成功\nif [ -d $yz_export_archive ] ; then\n\techo \"项目构建成功，开始导出 ipa 文件🚀🚀🚀\"\nelse\n\techo \"项目构建失败😢😢😢\"\n\texit 1\nfi\n\n# 先删除yz_export_options_plist文件\nif [ -f $yz_export_options_plist ] ; then\n\trm -rf $yz_export_options_plist\nfi\n\n# 根据参数生成export_options_plist文件\n/usr/libexec/PlistBuddy -c  \"Add :method String ${yz_method}\"  $yz_export_options_plist\n/usr/libexec/PlistBuddy -c  \"Add :provisioningProfiles:\"  $yz_export_options_plist\n/usr/libexec/PlistBuddy -c  \"Add :provisioningProfiles:${yz_bundle_identifier} String ${yz_mobileprovision_name}\"  $yz_export_options_plist\n\n# 导出ipa文件\nxcodebuild  -exportArchive \\\n            -archivePath $yz_export_archive \\\n            -exportPath $yz_export_path \\\n            -exportOptionsPlist $yz_export_options_plist \\\n            -allowProvisioningUpdates            \n\n# 检查ipa文件是否存在\nif [ -f $yz_export_ipa ] ; then\n\techo \"导出 ipa 包成功🎉🎉🎉\"\n\topen $yz_export_path\nelse\n\techo \"导出 ipa 包失败😢😢😢\"\n\texit 1\nfi\n\n# 删除 yz_export_options_plist 文件（中间文件）\nif [ -f $yz_export_options_plist ] ; then\n\trm -f $yz_export_options_plist\nfi\n\n# 输出打包总用时\necho \"使用脚本打包总耗时：${SECONDS}s\"\n"
  }
]