Full Code of micyo202/YZAuthID for AI

master 417c18531fe3 cached
24 files
48.9 KB
14.9k tokens
1 requests
Download .txt
Repository: micyo202/YZAuthID
Branch: master
Commit: 417c18531fe3
Files: 24
Total size: 48.9 KB

Directory structure:
gitextract_tlh1k132/

├── .gitignore
├── .travis.yml
├── ExportOptions.plist
├── LICENSE
├── README.md
├── Supporting Files/
│   ├── AppDelegate.h
│   ├── AppDelegate.m
│   ├── Assets.xcassets/
│   │   └── AppIcon.appiconset/
│   │       └── Contents.json
│   ├── Base.lproj/
│   │   └── LaunchScreen.storyboard
│   ├── Images.xcassets/
│   │   ├── Contents.json
│   │   ├── auth_face.imageset/
│   │   │   └── Contents.json
│   │   └── auth_finger.imageset/
│   │       └── Contents.json
│   ├── Info.plist
│   └── main.m
├── YZAuthID/
│   ├── YZAuthID.h
│   └── YZAuthID.m
├── YZAuthID.podspec
├── YZAuthID.xcodeproj/
│   ├── project.pbxproj
│   └── project.xcworkspace/
│       ├── contents.xcworkspacedata
│       └── xcshareddata/
│           └── IDEWorkspaceChecks.plist
├── YZAuthIDDemo/
│   ├── Base.lproj/
│   │   └── Main.storyboard
│   ├── ViewController.h
│   └── ViewController.m
└── archive.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## Build generated
build/
DerivedData/

## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/

## Other
*.moved-aside
*.xccheckout
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output

# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/


================================================
FILE: .travis.yml
================================================
language: objective-c
osx_image: xcode10
xcode_project: YZAuthID.xcodeproj
xcode_scheme: YZAuthID

before_install:
- env
- xcodebuild -version
- xcodebuild -showsdks
- xcpretty --version

script:
- set -o pipefail
- xcodebuild clean build -project "$TRAVIS_XCODE_PROJECT" -scheme "$TRAVIS_XCODE_SCHEME" -sdk iphonesimulator PLATFORM_NAME=iphonesimulator -configuration Debug | xcpretty -c


================================================
FILE: ExportOptions.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>compileBitcode</key>
	<false/>
	<key>method</key>
	<string>development</string>
</dict>
</plist>

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 Yanzheng

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# YZAuthID

[![Build Status](https://travis-ci.org/micyo202/YZAuthID.svg)](https://travis-ci.org/micyo202/YZAuthID)
[![Version](https://img.shields.io/badge/version-2.1.0-yellow.svg)](https://github.com/micyo202/YZAuthID)
[![Cocoapods](https://img.shields.io/badge/pod-1.10.0-green.svg)](https://cocoapods.org/?q=YZAuthID)
[![Platform](https://img.shields.io/badge/platform-ios-red.svg)](https://github.com/micyo202/YZAuthID)
[![License MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://github.com/micyo202/YZAuthID/blob/master/LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/micyo202/YZAuthID.svg?style=social&label=Stars)](https://github.com/micyo202/YZAuthID)
[![GitHub forks](https://img.shields.io/github/forks/micyo202/YZAuthID.svg?style=social&label=Fork)](https://github.com/micyo202/YZAuthID)

仅需一个回调方法即可轻松实现iOS TouchID(指纹)/ FaceID(面容)验证功能,代码简洁易懂。

#### 详细使用方法及介绍请参考[简书](https://www.jianshu.com/p/da752036b2f4)

#### 实例效果图:

<img src="https://github.com/micyo202/YZAuthID/raw/master/auth_finger_1.png" alt="指纹1" title="指纹界面">

<img src="https://github.com/micyo202/YZAuthID/raw/master/auth_finger_2.png" alt="指纹2" title="开始认证">

<img src="https://github.com/micyo202/YZAuthID/raw/master/auth_finger_3.png" alt="指纹3" title="认证失败">

<img src="https://github.com/micyo202/YZAuthID/raw/master/auth_face_1.png" alt="面容1" title="面容界面">

<img src="https://github.com/micyo202/YZAuthID/raw/master/auth_face_2.png" alt="面容2" title="开始认证">

<img src="https://github.com/micyo202/YZAuthID/raw/master/auth_face_3.png" alt="面容3" title="认证失败">


================================================
FILE: Supporting Files/AppDelegate.h
================================================
//
//  AppDelegate.h
//  YZAuthID
//
//  Created by Apple on 2018/07/26.
//  Copyright © 2018年 Yanzheng. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end



================================================
FILE: Supporting Files/AppDelegate.m
================================================
//
//  AppDelegate.m
//  YZAuthID
//
//  Created by Apple on 2018/07/26.
//  Copyright © 2018年 Yanzheng. All rights reserved.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    // 设置顶部状态栏字体为白色
    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
    
    return YES;
}


- (void)applicationWillResignActive:(UIApplication *)application {
    // 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.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    // 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.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    // 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.
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    // 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.
}


- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}


@end


================================================
FILE: Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "83.5x83.5",
      "scale" : "2x"
    },
    {
      "idiom" : "ios-marketing",
      "size" : "1024x1024",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Supporting Files/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: Supporting Files/Images.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Supporting Files/Images.xcassets/auth_face.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "auth_face@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Supporting Files/Images.xcassets/auth_finger.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "auth_finger@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Supporting Files/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(MARKETING_VERSION)</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>NSFaceIDUsageDescription</key>
	<string>允许设备访问Face ID</string>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>
</dict>
</plist>


================================================
FILE: Supporting Files/main.m
================================================
//
//  main.m
//  YZAuthID
//
//  Created by Apple on 2018/07/26.
//  Copyright © 2018年 Yanzheng. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}


================================================
FILE: YZAuthID/YZAuthID.h
================================================
/************************************************************
 Class    : YZAuthID.h
 Describe : TouchID/FaceID 认证方法
 Company  : Micyo
 Author   : Yanzheng
 Date     : 2018-07-26
 Version  : 2.0
 Declare  : Copyright © 2018 Yanzheng. All rights reserved.
 ************************************************************/

#import <LocalAuthentication/LocalAuthentication.h>

/**
 *  TouchID/FaceID 状态
 */
typedef NS_ENUM(NSUInteger, YZAuthIDState){
    
    /**
     *  当前设备不支持TouchID/FaceID
     */
    YZAuthIDStateNotSupport = 0,
    /**
     *  TouchID/FaceID 验证成功
     */
    YZAuthIDStateSuccess = 1,
    
    /**
     *  TouchID/FaceID 验证失败
     */
    YZAuthIDStateFail = 2,
    /**
     *  TouchID/FaceID 被用户手动取消
     */
    YZAuthIDStateUserCancel = 3,
    /**
     *  用户不使用TouchID/FaceID,选择手动输入密码
     */
    YZAuthIDStateInputPassword = 4,
    /**
     *  TouchID/FaceID 被系统取消 (如遇到来电,锁屏,按了Home键等)
     */
    YZAuthIDStateSystemCancel = 5,
    /**
     *  TouchID/FaceID 无法启动,因为用户没有设置密码
     */
    YZAuthIDStatePasswordNotSet = 6,
    /**
     *  TouchID/FaceID 无法启动,因为用户没有设置TouchID/FaceID
     */
    YZAuthIDStateTouchIDNotSet = 7,
    /**
     *  TouchID/FaceID 无效
     */
    YZAuthIDStateTouchIDNotAvailable = 8,
    /**
     *  TouchID/FaceID 被锁定(连续多次验证TouchID/FaceID失败,系统需要用户手动输入密码)
     */
    YZAuthIDStateTouchIDLockout = 9,
    /**
     *  当前软件被挂起并取消了授权 (如App进入了后台等)
     */
    YZAuthIDStateAppCancel = 10,
    /**
     *  当前软件被挂起并取消了授权 (LAContext对象无效)
     */
    YZAuthIDStateInvalidContext = 11,
    /**
     *  系统版本不支持TouchID/FaceID (必须高于iOS 8.0才能使用)
     */
    YZAuthIDStateVersionNotSupport = 12
};


@interface YZAuthID : LAContext

typedef void (^YZAuthIDStateBlock)(YZAuthIDState state, NSError *error);

/**
 * 启动TouchID/FaceID进行验证
 * @param describe TouchID/FaceID显示的描述
 * @param block 回调状态的block
 */
- (void)yz_showAuthIDWithDescribe:(NSString *)describe block:(YZAuthIDStateBlock)block;

@end


================================================
FILE: YZAuthID/YZAuthID.m
================================================
/************************************************************
 Class    : YZAuthID.m
 Describe : TouchID/FaceID 认证方法
 Company  : Micyo
 Author   : Yanzheng
 Date     : 2018-07-26
 Version  : 2.0
 Declare  : Copyright © 2018 Yanzheng. All rights reserved.
 ************************************************************/

#import "YZAuthID.h"
#import <UIKit/UIKit.h>

#define iPhoneX (UIScreen.mainScreen.bounds.size.width >= 375.f && UIScreen.mainScreen.bounds.size.height >= 812.f)

@implementation YZAuthID

+ (instancetype)sharedInstance {
    static YZAuthID *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[YZAuthID alloc] init];
    });
    return instance;
}

- (void)yz_showAuthIDWithDescribe:(NSString *)describe block:(YZAuthIDStateBlock)block {
    if(!describe) {
        if(iPhoneX){
            describe = @"验证已有面容";
        }else{
            describe = @"通过Home键验证已有指纹";
        }
    }
    
    if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0) {
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"系统版本不支持TouchID/FaceID (必须高于iOS 8.0才能使用)");
            block(YZAuthIDStateVersionNotSupport, nil);
        });
        
        return;
    }
    
    LAContext *context = [[LAContext alloc] init];
    
    // 认证失败提示信息,为 @"" 则不提示
    context.localizedFallbackTitle = @"输入密码";
    
    NSError *error = nil;
    
    // LAPolicyDeviceOwnerAuthenticationWithBiometrics: 用TouchID/FaceID验证
    // LAPolicyDeviceOwnerAuthentication: 用TouchID/FaceID或密码验证, 默认是错误两次或锁定后, 弹出输入密码界面(本案例使用)
    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]) {
        [context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:describe reply:^(BOOL success, NSError * _Nullable error) {
            
            if (success) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"TouchID/FaceID 验证成功");
                    block(YZAuthIDStateSuccess, error);
                });
            }else if(error){
                
                if (@available(iOS 11.0, *)) {
                    switch (error.code) {
                        case LAErrorAuthenticationFailed:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID/FaceID 验证失败");
                                block(YZAuthIDStateFail, error);
                            });
                            break;
                        }
                        case LAErrorUserCancel:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID/FaceID 被用户手动取消");
                                block(YZAuthIDStateUserCancel, error);
                            });
                        }
                            break;
                        case LAErrorUserFallback:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"用户不使用TouchID/FaceID,选择手动输入密码");
                                block(YZAuthIDStateInputPassword, error);
                            });
                        }
                            break;
                        case LAErrorSystemCancel:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID/FaceID 被系统取消 (如遇到来电,锁屏,按了Home键等)");
                                block(YZAuthIDStateSystemCancel, error);
                            });
                        }
                            break;
                        case LAErrorPasscodeNotSet:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID/FaceID 无法启动,因为用户没有设置密码");
                                block(YZAuthIDStatePasswordNotSet, error);
                            });
                        }
                            break;
                            //case LAErrorTouchIDNotEnrolled:{
                        case LAErrorBiometryNotEnrolled:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID/FaceID 无法启动,因为用户没有设置TouchID/FaceID");
                                block(YZAuthIDStateTouchIDNotSet, error);
                            });
                        }
                            break;
                            //case LAErrorTouchIDNotAvailable:{
                        case LAErrorBiometryNotAvailable:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID/FaceID 无效");
                                block(YZAuthIDStateTouchIDNotAvailable, error);
                            });
                        }
                            break;
                            //case LAErrorTouchIDLockout:{
                        case LAErrorBiometryLockout:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID/FaceID 被锁定(连续多次验证TouchID/FaceID失败,系统需要用户手动输入密码)");
                                block(YZAuthIDStateTouchIDLockout, error);
                            });
                        }
                            break;
                        case LAErrorAppCancel:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"当前软件被挂起并取消了授权 (如App进入了后台等)");
                                block(YZAuthIDStateAppCancel, error);
                            });
                        }
                            break;
                        case LAErrorInvalidContext:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"当前软件被挂起并取消了授权 (LAContext对象无效)");
                                block(YZAuthIDStateInvalidContext, error);
                            });
                        }
                            break;
                        default:
                            break;
                    }
                } else {
                    // iOS 11.0以下的版本只有 TouchID 认证
                    switch (error.code) {
                        case LAErrorAuthenticationFailed:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID 验证失败");
                                block(YZAuthIDStateFail, error);
                            });
                            break;
                        }
                        case LAErrorUserCancel:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID 被用户手动取消");
                                block(YZAuthIDStateUserCancel, error);
                            });
                        }
                            break;
                        case LAErrorUserFallback:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"用户不使用TouchID,选择手动输入密码");
                                block(YZAuthIDStateInputPassword, error);
                            });
                        }
                            break;
                        case LAErrorSystemCancel:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID 被系统取消 (如遇到来电,锁屏,按了Home键等)");
                                block(YZAuthIDStateSystemCancel, error);
                            });
                        }
                            break;
                        case LAErrorPasscodeNotSet:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID 无法启动,因为用户没有设置密码");
                                block(YZAuthIDStatePasswordNotSet, error);
                            });
                        }
                            break;
                        case LAErrorBiometryNotEnrolled:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID 无法启动,因为用户没有设置TouchID");
                                block(YZAuthIDStateTouchIDNotSet, error);
                            });
                        }
                            break;
                            //case :{
                        case LAErrorBiometryNotAvailable:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID 无效");
                                block(YZAuthIDStateTouchIDNotAvailable, error);
                            });
                        }
                            break;
                        case LAErrorBiometryLockout:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"TouchID 被锁定(连续多次验证TouchID失败,系统需要用户手动输入密码)");
                                block(YZAuthIDStateTouchIDLockout, error);
                            });
                        }
                            break;
                        case LAErrorAppCancel:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"当前软件被挂起并取消了授权 (如App进入了后台等)");
                                block(YZAuthIDStateAppCancel, error);
                            });
                        }
                            break;
                        case LAErrorInvalidContext:{
                            dispatch_async(dispatch_get_main_queue(), ^{
                                NSLog(@"当前软件被挂起并取消了授权 (LAContext对象无效)");
                                block(YZAuthIDStateInvalidContext, error);
                            });
                        }
                            break;
                        default:
                            break;
                    }
                }
                
            }
        }];
        
    }else{
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"当前设备不支持TouchID/FaceID");
            block(YZAuthIDStateNotSupport, error);
        });
        
    }
}

@end


================================================
FILE: YZAuthID.podspec
================================================
Pod::Spec.new do |s|
    s.name         = 'YZAuthID'
    s.version      = '2.1.0'
    s.summary      = 'TouchID/FaceID auth.'
    s.homepage     = 'https://github.com/micyo202/YZAuthID'
    s.license      = { :type => 'MIT', :file => 'LICENSE' }
    s.authors      = {'Yanzheng' => 'micyo202@163.com'}
    s.platform     = :ios, '12.0'
    s.ios.deployment_target = '12.0'
    s.source       = {:git => 'https://github.com/micyo202/YZAuthID.git', :tag => s.version}
    s.source_files = 'YZAuthID/**/*.{h,m}'
    s.requires_arc = true
end


================================================
FILE: YZAuthID.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 48;
	objects = {

/* Begin PBXBuildFile section */
		182B79E31FECDBAF005E0E81 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79E21FECDBAF005E0E81 /* AppDelegate.m */; };
		182B79E61FECDBAF005E0E81 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79E51FECDBAF005E0E81 /* ViewController.m */; };
		182B79E91FECDBAF005E0E81 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 182B79E71FECDBAF005E0E81 /* Main.storyboard */; };
		182B79EB1FECDBAF005E0E81 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 182B79EA1FECDBAF005E0E81 /* Assets.xcassets */; };
		182B79EE1FECDBAF005E0E81 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 182B79EC1FECDBAF005E0E81 /* LaunchScreen.storyboard */; };
		182B79F11FECDBAF005E0E81 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79F01FECDBAF005E0E81 /* main.m */; };
		182B79FC1FECDCDB005E0E81 /* YZAuthID.m in Sources */ = {isa = PBXBuildFile; fileRef = 182B79FB1FECDCDB005E0E81 /* YZAuthID.m */; };
		182B79FE1FECEE5A005E0E81 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 182B79FD1FECEE5A005E0E81 /* Images.xcassets */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		182B79DE1FECDBAF005E0E81 /* YZAuthID.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YZAuthID.app; sourceTree = BUILT_PRODUCTS_DIR; };
		182B79E11FECDBAF005E0E81 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		182B79E21FECDBAF005E0E81 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		182B79E41FECDBAF005E0E81 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
		182B79E51FECDBAF005E0E81 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
		182B79E81FECDBAF005E0E81 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		182B79EA1FECDBAF005E0E81 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		182B79ED1FECDBAF005E0E81 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		182B79EF1FECDBAF005E0E81 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		182B79F01FECDBAF005E0E81 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		182B79FA1FECDCDB005E0E81 /* YZAuthID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YZAuthID.h; sourceTree = "<group>"; };
		182B79FB1FECDCDB005E0E81 /* YZAuthID.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YZAuthID.m; sourceTree = "<group>"; };
		182B79FD1FECEE5A005E0E81 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		182B79DB1FECDBAF005E0E81 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		182B79D51FECDBAF005E0E81 = {
			isa = PBXGroup;
			children = (
				182B79F91FECDBF6005E0E81 /* Supporting Files */,
				182B79F71FECDBD6005E0E81 /* YZAuthIDDemo */,
				182B79E01FECDBAF005E0E81 /* YZAuthID */,
				182B79DF1FECDBAF005E0E81 /* Products */,
			);
			sourceTree = "<group>";
		};
		182B79DF1FECDBAF005E0E81 /* Products */ = {
			isa = PBXGroup;
			children = (
				182B79DE1FECDBAF005E0E81 /* YZAuthID.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		182B79E01FECDBAF005E0E81 /* YZAuthID */ = {
			isa = PBXGroup;
			children = (
				182B79FA1FECDCDB005E0E81 /* YZAuthID.h */,
				182B79FB1FECDCDB005E0E81 /* YZAuthID.m */,
			);
			path = YZAuthID;
			sourceTree = "<group>";
		};
		182B79F71FECDBD6005E0E81 /* YZAuthIDDemo */ = {
			isa = PBXGroup;
			children = (
				182B79E41FECDBAF005E0E81 /* ViewController.h */,
				182B79E51FECDBAF005E0E81 /* ViewController.m */,
				182B79E71FECDBAF005E0E81 /* Main.storyboard */,
			);
			path = YZAuthIDDemo;
			sourceTree = "<group>";
		};
		182B79F91FECDBF6005E0E81 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				182B79E11FECDBAF005E0E81 /* AppDelegate.h */,
				182B79E21FECDBAF005E0E81 /* AppDelegate.m */,
				182B79EA1FECDBAF005E0E81 /* Assets.xcassets */,
				182B79EC1FECDBAF005E0E81 /* LaunchScreen.storyboard */,
				182B79EF1FECDBAF005E0E81 /* Info.plist */,
				182B79F01FECDBAF005E0E81 /* main.m */,
				182B79FD1FECEE5A005E0E81 /* Images.xcassets */,
			);
			path = "Supporting Files";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		182B79DD1FECDBAF005E0E81 /* YZAuthID */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 182B79F41FECDBAF005E0E81 /* Build configuration list for PBXNativeTarget "YZAuthID" */;
			buildPhases = (
				182B79DA1FECDBAF005E0E81 /* Sources */,
				182B79DB1FECDBAF005E0E81 /* Frameworks */,
				182B79DC1FECDBAF005E0E81 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = YZAuthID;
			productName = YZAuthID;
			productReference = 182B79DE1FECDBAF005E0E81 /* YZAuthID.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		182B79D61FECDBAF005E0E81 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0920;
				ORGANIZATIONNAME = Yanzheng;
				TargetAttributes = {
					182B79DD1FECDBAF005E0E81 = {
						CreatedOnToolsVersion = 9.2;
						ProvisioningStyle = Automatic;
					};
				};
			};
			buildConfigurationList = 182B79D91FECDBAF005E0E81 /* Build configuration list for PBXProject "YZAuthID" */;
			compatibilityVersion = "Xcode 8.0";
			developmentRegion = en;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = 182B79D51FECDBAF005E0E81;
			productRefGroup = 182B79DF1FECDBAF005E0E81 /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				182B79DD1FECDBAF005E0E81 /* YZAuthID */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		182B79DC1FECDBAF005E0E81 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				182B79EE1FECDBAF005E0E81 /* LaunchScreen.storyboard in Resources */,
				182B79FE1FECEE5A005E0E81 /* Images.xcassets in Resources */,
				182B79EB1FECDBAF005E0E81 /* Assets.xcassets in Resources */,
				182B79E91FECDBAF005E0E81 /* Main.storyboard in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		182B79DA1FECDBAF005E0E81 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				182B79E61FECDBAF005E0E81 /* ViewController.m in Sources */,
				182B79F11FECDBAF005E0E81 /* main.m in Sources */,
				182B79E31FECDBAF005E0E81 /* AppDelegate.m in Sources */,
				182B79FC1FECDCDB005E0E81 /* YZAuthID.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
		182B79E71FECDBAF005E0E81 /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				182B79E81FECDBAF005E0E81 /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
		182B79EC1FECDBAF005E0E81 /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				182B79ED1FECDBAF005E0E81 /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		182B79F21FECDBAF005E0E81 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				CODE_SIGN_IDENTITY = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
			};
			name = Debug;
		};
		182B79F31FECDBAF005E0E81 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				CODE_SIGN_IDENTITY = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu11;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		182B79F51FECDBAF005E0E81 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = YPP9C225DR;
				INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				MARKETING_VERSION = 2.1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.yan.YZAuthID;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		182B79F61FECDBAF005E0E81 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = YPP9C225DR;
				INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				MARKETING_VERSION = 2.1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.yan.YZAuthID;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		182B79D91FECDBAF005E0E81 /* Build configuration list for PBXProject "YZAuthID" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				182B79F21FECDBAF005E0E81 /* Debug */,
				182B79F31FECDBAF005E0E81 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		182B79F41FECDBAF005E0E81 /* Build configuration list for PBXNativeTarget "YZAuthID" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				182B79F51FECDBAF005E0E81 /* Debug */,
				182B79F61FECDBAF005E0E81 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 182B79D61FECDBAF005E0E81 /* Project object */;
}


================================================
FILE: YZAuthID.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:YZAuthID.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: YZAuthID.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>


================================================
FILE: YZAuthIDDemo/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<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">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>


================================================
FILE: YZAuthIDDemo/ViewController.h
================================================
/************************************************************
 Class    : ViewController.h
 Describe : YZAuthID 认证方法示例代码
 Company  : Micyo
 Author   : Yanzheng
 Date     : 2018-07-26
 Version  : 2.0
 Declare  : Copyright © 2018 Yanzheng. All rights reserved.
 ************************************************************/

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController


@end



================================================
FILE: YZAuthIDDemo/ViewController.m
================================================
/************************************************************
 Class    : ViewController.m
 Describe : YZAuthID 认证方法示例代码
 Company  : Micyo
 Author   : Yanzheng
 Date     : 2018-07-26
 Version  : 2.0
 Declare  : Copyright © 2018 Yanzheng. All rights reserved.
 ************************************************************/

#import "ViewController.h"
#import "YZAuthID.h"

#define iPhoneX (UIScreen.mainScreen.bounds.size.width == 375.f && UIScreen.mainScreen.bounds.size.height == 812.f)

@interface ViewController ()

@property (nonatomic, strong) UILabel *hintLabel;           // 提示标题
@property (nonatomic, strong) UIImageView *imageView;       // 图标
@property (nonatomic, strong) UIButton *actionBtn;          // 按钮

@property (nonatomic, copy) NSString *authImage;            // 认证图标名
@property (nonatomic, copy) NSString *authName;             // 认证名称

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.view.backgroundColor = UIColor.whiteColor;
    
    [self initialize];
}

#pragma mark - 初始化方法
- (void)initialize {
    // 设置值
    if(iPhoneX){
        self.authImage = @"auth_face";
        self.authName = @"面容";
    }else{
        self.authImage = @"auth_finger";
        self.authName = @"指纹";
    }
    
    // 添加组件
    [self.view addSubview:self.hintLabel];
    [self.view addSubview:self.imageView];
    [self.view addSubview:self.actionBtn];
    
    // 开始认证
    [self authVerification];
}

#pragma mark - 懒加载各组件
- (UILabel *)hintLabel {
    if(!_hintLabel){
        _hintLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 160, self.view.frame.size.width, 60)];
        _hintLabel.font = [UIFont systemFontOfSize:22.f];
        _hintLabel.textAlignment = NSTextAlignmentCenter;
        _hintLabel.numberOfLines = 0;
        _hintLabel.text = [NSString stringWithFormat:@"YZAuth\n验证%@以进行登录", self.authName];
    }
    return _hintLabel;
}

- (UIImageView *)imageView {
    if(!_imageView){
        
        _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2 - 35, self.hintLabel.frame.origin.y + 130, 70, 70)];
        _imageView.image = [UIImage imageNamed:self.authImage];
    }
    return _imageView;
}

- (UIButton *)actionBtn {
    if(!_actionBtn){
        _actionBtn = [UIButton buttonWithType:UIButtonTypeSystem];
        _actionBtn.frame = CGRectMake(60, self.imageView.frame.origin.y + 190, self.view.frame.size.width - 120, 40);
        [_actionBtn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
        _actionBtn.titleLabel.font = [UIFont systemFontOfSize:18.f];
        [_actionBtn setTitle:[NSString stringWithFormat:@"点击验证%@", self.authName] forState:UIControlStateNormal];
        [_actionBtn setBackgroundColor:[UIColor colorWithRed:123/255.f green:188/255.f blue:231/255.f alpha:1]];
        _actionBtn.layer.cornerRadius = 5.f;
        _actionBtn.layer.masksToBounds = YES;
        [_actionBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _actionBtn;
}

#pragma mark - 按钮点击事件
- (void)btnClicked:(UIButton *)sender {
    // 唤起指纹、面容ID验证
    [self authVerification];
}

#pragma mark - 验证TouchID/FaceID
- (void)authVerification {
    
    YZAuthID *authID = [[YZAuthID alloc] init];
    
    [authID yz_showAuthIDWithDescribe:nil block:^(YZAuthIDState state, NSError *error) {
        
        if (state == YZAuthIDStateNotSupport) { // 不支持TouchID/FaceID
            NSLog(@"对不起,当前设备不支持指纹/面容ID");
        } else if(state == YZAuthIDStateFail) { // 认证失败
            NSLog(@"指纹/面容ID不正确,认证失败");
        } else if(state == YZAuthIDStateTouchIDLockout) {   // 多次错误,已被锁定
            NSLog(@"多次错误,指纹/面容ID已被锁定,请到手机解锁界面输入密码");
        } else if (state == YZAuthIDStateSuccess) { // TouchID/FaceID验证成功
            NSLog(@"认证成功!");
        }
        
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end


================================================
FILE: archive.sh
================================================
#!/bin/bash

# 打包脚本使用说明:
# 1.修改:yz_cocopods、yz_project、yz_scheme参数
# 2.执行:./archive.sh 默认打 Debug 包
# 3.执行:./archive.sh Release 打 Release 包

# 用Cocopods管理的.xcworkspace项目,赋值true;用Xcode默认创建的.xcodeproj,赋值false
yz_cocopods=true
# 工程名称(project的名称)
yz_project=YZAuthID
# scheme名称(也就是工程的target名称)
yz_scheme=YZAuthID
# Debug Release
if [ -z $1 ]; then
	yz_configuration=Debug
else
	yz_configuration=$1
fi
# method,打包的方式(方式分别为 development, ad-hoc, app-store, enterprise)
yz_method=development
# 日期时间
yz_date=`date +%Y%m%d_%H%M%S`
# 获取当前脚本所在目录
yz_script_path=$( cd $( dirname $0 ) && pwd )
# 工程目录
yz_project_path=$yz_script_path
# 指定输出导出文件夹路径
yz_export_path=$yz_project_path/package/$yz_date
# 指定输出归档文件路径
yz_export_archive=$yz_export_path/$yz_scheme.xcarchive
# 指定输出ipa名称
yz_export_ipa=$yz_export_path/$yz_scheme.ipa
# 指定导出ipa包需要用到的plist配置文件的路径
yz_export_options_plist=$yz_project_path/ExportOptions.plist

#  下面两个参数只是在手动指定Pofile文件的时候用到,如果使用Xcode自动管理Profile,直接留空就好
# (跟method对应的)mobileprovision文件名,需要先双击安装.mobileprovision文件.手动管理Profile时必填
yz_mobileprovision_name=""
# 项目的bundleID,手动管理Profile时必填
yz_bundle_identifier=""

# 输出参数
echo --------------------脚本配置参数检查--------------------
echo yz_cocopods=$yz_cocopods
echo yz_project=$yz_project
echo yz_scheme=$yz_scheme
echo yz_configuration=$yz_configuration
echo yz_method=$yz_method
echo yz_date=$yz_date
echo yz_script_path=$yz_script_path
echo yz_project_path=$yz_project_path
echo yz_export_path=$yz_export_path
echo yz_export_archive=$yz_export_archive
echo yz_export_ipa=$yz_export_ipa
echo yz_export_options_plist=$yz_export_options_plist

if [[ "Debug" != $yz_configuration ]] && [[ "Release" != $yz_configuration ]]; then
	echo "参数yz_configuration=${1}不正确,yz_configuration取值范围:Debug(默认)、Release"
	exit 1
fi

# 开发打包
echo --------------------自动打包脚本执行--------------------

# 进入项目工程目录
cd $yz_project_path

# 指定输出文件目录不存在则创建
if [ -d $yz_export_path ] ; then
	echo $yz_export_path
else
	mkdir -pv $yz_export_path
fi

# 判断是Cocoapods还是Xcode项目
if $yz_cocoapods ; then

echo -------------------Cocoapods 项目打包-------------------

# pods 添加
pod install

# 打包脚本执行
xcodebuild archive \
-workspace $yz_project.xcworkspace \
-scheme $yz_scheme \
-configuration $yz_configuration \
-archivePath $yz_export_archive \
clean \
build

else

echo ---------------------Xcode 项目打包---------------------

xcodebuild archive \
-project $yz_project.xcodeproj \
-scheme $yz_scheme \
-configuration $yz_configuration \
-archivePath $yz_export_archive \
clean \
build

fi

# 检查构建是否成功
if [ -d $yz_export_archive ] ; then
	echo "项目构建成功,开始导出 ipa 文件🚀🚀🚀"
else
	echo "项目构建失败😢😢😢"
	exit 1
fi

# 先删除yz_export_options_plist文件
if [ -f $yz_export_options_plist ] ; then
	rm -rf $yz_export_options_plist
fi

# 根据参数生成export_options_plist文件
/usr/libexec/PlistBuddy -c  "Add :method String ${yz_method}"  $yz_export_options_plist
/usr/libexec/PlistBuddy -c  "Add :provisioningProfiles:"  $yz_export_options_plist
/usr/libexec/PlistBuddy -c  "Add :provisioningProfiles:${yz_bundle_identifier} String ${yz_mobileprovision_name}"  $yz_export_options_plist

# 导出ipa文件
xcodebuild  -exportArchive \
            -archivePath $yz_export_archive \
            -exportPath $yz_export_path \
            -exportOptionsPlist $yz_export_options_plist \
            -allowProvisioningUpdates            

# 检查ipa文件是否存在
if [ -f $yz_export_ipa ] ; then
	echo "导出 ipa 包成功🎉🎉🎉"
	open $yz_export_path
else
	echo "导出 ipa 包失败😢😢😢"
	exit 1
fi

# 删除 yz_export_options_plist 文件(中间文件)
if [ -f $yz_export_options_plist ] ; then
	rm -f $yz_export_options_plist
fi

# 输出打包总用时
echo "使用脚本打包总耗时:${SECONDS}s"
Download .txt
gitextract_tlh1k132/

├── .gitignore
├── .travis.yml
├── ExportOptions.plist
├── LICENSE
├── README.md
├── Supporting Files/
│   ├── AppDelegate.h
│   ├── AppDelegate.m
│   ├── Assets.xcassets/
│   │   └── AppIcon.appiconset/
│   │       └── Contents.json
│   ├── Base.lproj/
│   │   └── LaunchScreen.storyboard
│   ├── Images.xcassets/
│   │   ├── Contents.json
│   │   ├── auth_face.imageset/
│   │   │   └── Contents.json
│   │   └── auth_finger.imageset/
│   │       └── Contents.json
│   ├── Info.plist
│   └── main.m
├── YZAuthID/
│   ├── YZAuthID.h
│   └── YZAuthID.m
├── YZAuthID.podspec
├── YZAuthID.xcodeproj/
│   ├── project.pbxproj
│   └── project.xcworkspace/
│       ├── contents.xcworkspacedata
│       └── xcshareddata/
│           └── IDEWorkspaceChecks.plist
├── YZAuthIDDemo/
│   ├── Base.lproj/
│   │   └── Main.storyboard
│   ├── ViewController.h
│   └── ViewController.m
└── archive.sh
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (57K chars).
[
  {
    "path": ".gitignore",
    "chars": 1398,
    "preview": "# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n"
  },
  {
    "path": ".travis.yml",
    "chars": 389,
    "preview": "language: objective-c\nosx_image: xcode10\nxcode_project: YZAuthID.xcodeproj\nxcode_scheme: YZAuthID\n\nbefore_install:\n- env"
  },
  {
    "path": "ExportOptions.plist",
    "chars": 273,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "LICENSE",
    "chars": 1065,
    "preview": "MIT License\n\nCopyright (c) 2018 Yanzheng\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "README.md",
    "chars": 1573,
    "preview": "# YZAuthID\n\n[![Build Status](https://travis-ci.org/micyo202/YZAuthID.svg)](https://travis-ci.org/micyo202/YZAuthID)\n[![V"
  },
  {
    "path": "Supporting Files/AppDelegate.h",
    "chars": 273,
    "preview": "//\n//  AppDelegate.h\n//  YZAuthID\n//\n//  Created by Apple on 2018/07/26.\n//  Copyright © 2018年 Yanzheng. All rights rese"
  },
  {
    "path": "Supporting Files/AppDelegate.m",
    "chars": 2150,
    "preview": "//\n//  AppDelegate.m\n//  YZAuthID\n//\n//  Created by Apple on 2018/07/26.\n//  Copyright © 2018年 Yanzheng. All rights rese"
  },
  {
    "path": "Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1590,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "Supporting Files/Base.lproj/LaunchScreen.storyboard",
    "chars": 1681,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "Supporting Files/Images.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Supporting Files/Images.xcassets/auth_face.imageset/Contents.json",
    "chars": 309,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Supporting Files/Images.xcassets/auth_finger.imageset/Contents.json",
    "chars": 311,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "Supporting Files/Info.plist",
    "chars": 1612,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Supporting Files/main.m",
    "chars": 330,
    "preview": "//\n//  main.m\n//  YZAuthID\n//\n//  Created by Apple on 2018/07/26.\n//  Copyright © 2018年 Yanzheng. All rights reserved.\n/"
  },
  {
    "path": "YZAuthID/YZAuthID.h",
    "chars": 1929,
    "preview": "/************************************************************\n Class    : YZAuthID.h\n Describe : TouchID/FaceID 认证方法\n Co"
  },
  {
    "path": "YZAuthID/YZAuthID.m",
    "chars": 10266,
    "preview": "/************************************************************\n Class    : YZAuthID.m\n Describe : TouchID/FaceID 认证方法\n Co"
  },
  {
    "path": "YZAuthID.podspec",
    "chars": 539,
    "preview": "Pod::Spec.new do |s|\n    s.name         = 'YZAuthID'\n    s.version      = '2.1.0'\n    s.summary      = 'TouchID/FaceID a"
  },
  {
    "path": "YZAuthID.xcodeproj/project.pbxproj",
    "chars": 14201,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 48;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "YZAuthID.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 153,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:YZAuthID.xcodep"
  },
  {
    "path": "YZAuthID.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "YZAuthIDDemo/Base.lproj/Main.storyboard",
    "chars": 1703,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "YZAuthIDDemo/ViewController.h",
    "chars": 401,
    "preview": "/************************************************************\n Class    : ViewController.h\n Describe : YZAuthID 认证方法示例代码"
  },
  {
    "path": "YZAuthIDDemo/ViewController.m",
    "chars": 4061,
    "preview": "/************************************************************\n Class    : ViewController.m\n Describe : YZAuthID 认证方法示例代码"
  },
  {
    "path": "archive.sh",
    "chars": 3572,
    "preview": "#!/bin/bash\n\n# 打包脚本使用说明:\n# 1.修改:yz_cocopods、yz_project、yz_scheme参数\n# 2.执行:./archive.sh 默认打 Debug 包\n# 3.执行:./archive.sh R"
  }
]

About this extraction

This page contains the full source code of the micyo202/YZAuthID GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (48.9 KB), approximately 14.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!