├── .DS_Store
├── image.png
├── image2.png
├── JHVerificationCodeView
├── .DS_Store
├── ViewController.h
├── NextViewController.h
├── AppDelegate.h
├── main.m
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── AppDelegate.m
├── NextViewController.m
├── JHVerificationCodeView
│ ├── JHVerificationCodeView.h
│ └── JHVerificationCodeView.m
└── ViewController.m
├── JHVerificationCodeView.xcodeproj
├── xcuserdata
│ ├── mac1.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ ├── apple.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ ├── xuejinghao.xcuserdatad
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── haocold.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── JHVerificationCodeView.xcscheme
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ ├── mac1.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── apple.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── haocold.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── xuejinghao.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── JHVerificationCodeView.podspec
├── JHVerificationCodeViewTests
├── Info.plist
└── JHVerificationCodeViewTests.m
├── LICENSE
├── CHANGELOG.md
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/.DS_Store
--------------------------------------------------------------------------------
/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/image.png
--------------------------------------------------------------------------------
/image2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/image2.png
--------------------------------------------------------------------------------
/JHVerificationCodeView/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/JHVerificationCodeView/.DS_Store
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/xcuserdata/mac1.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/mac1.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/mac1.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/haocold.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/haocold.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/xuejinghao.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh093/JHVerificationCodeView/HEAD/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcuserdata/xuejinghao.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/JHVerificationCodeView/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // JHVerificationCodeView
4 | //
5 | // Created by HaoCold on 2017/8/25.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/NextViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // NextViewController.h
3 | // JHVerificationCodeView
4 | //
5 | // Created by HaoCold on 2020/9/8.
6 | // Copyright © 2020 HaoCold. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface NextViewController : UIViewController
14 |
15 | @end
16 |
17 | NS_ASSUME_NONNULL_END
18 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // JHVerificationCodeView
4 | //
5 | // Created by HaoCold on 2017/8/25.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // JHVerificationCodeView
4 | //
5 | // Created by HaoCold on 2017/8/25.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/xcuserdata/mac1.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | JHVerificationCodeView.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/xcuserdata/xuejinghao.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | JHVerificationCodeView.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | JHVerificationCodeView.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 | s.name = "JHVerificationCodeView"
4 | s.version = "1.3.7"
5 | s.summary = "A simple Verification Code View."
6 | s.homepage = "https://github.com/xjh093/JHVerificationCodeView"
7 | s.license = "MIT"
8 | s.author = { "Haocold" => "xjh093@126.com" }
9 | s.platform = :ios, "8.0"
10 | s.source = { :git => "https://github.com/xjh093/JHVerificationCodeView.git", :tag => s.version }
11 | s.source_files = "JHVerificationCodeView/JHVerificationCodeView/*.{h,m}"
12 | s.framework = "UIKit"
13 | s.requires_arc = true
14 |
15 | end
16 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/xcuserdata/haocold.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | JHVerificationCodeView.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 088BF8A61F4FAF3C00B5863B
16 |
17 | primary
18 |
19 |
20 | 088BF8BF1F4FAF3C00B5863B
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/JHVerificationCodeViewTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 xjh093
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/JHVerificationCodeViewTests/JHVerificationCodeViewTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // JHVerificationCodeViewTests.m
3 | // JHVerificationCodeViewTests
4 | //
5 | // Created by HaoCold on 2017/8/25.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface JHVerificationCodeViewTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation JHVerificationCodeViewTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Logs
2 |
3 | ### 2020-09-08
4 | 1.add `autoShowKeyboardDelay`
5 | - 延迟弹出键盘
6 |
7 | ---
8 |
9 | ### 2020-09-01
10 | 1.add One Time Code
11 | - 验证码快捷自动填充
12 |
13 | ---
14 |
15 | ### 2019-12-24:
16 | 1. add `inputBoxFinishColors`、`underLineFinishColors`、`finishFonts`、`finishTextColors`.
17 | 2. add method `showInputFinishColorWithIndex:`
18 |
19 | ---
20 |
21 | ### 2019-08-28:
22 | 1. add `keyboardType` and `useSystemPasswordKeyboard`.
23 | - 键盘类型,系统密码键盘.
24 |
25 | ---
26 |
27 | ### 2019-08-23:
28 | 1. add `inputBlock`.
29 | - 输入回调.
30 |
31 | ---
32 |
33 | ### 2019-07-19:
34 | 1.add method `- (void)clear;`
35 | - 一键清空.
36 |
37 | 2.add `customInputHolder`.
38 | - 自定义输入占位字符.
39 |
40 | ---
41 |
42 | ### 2018-11-1:
43 | 1.add `underLineHighlightedColor`.
44 | - 下划线高亮.
45 |
46 | ### 2018-10-17
47 | 1.add `FlickerAnimation`,`underline`.
48 | - 光标动画,下划线.
49 |
50 | ---
51 |
52 | ### 2018-10-15
53 | 1.add `inputBoxCornerRadius`,`inputBoxHighlightedColor`,and `autoShowKeyboard`.
54 | - 输入框圆角,输入框高亮,自动显示键盘.
55 |
56 | ---
57 |
58 | ### 2018-10-11
59 | 1.add `inputType`.
60 | - 输入类型限制.
61 |
62 | ---
63 |
64 | ### 2018-6-25
65 | 1.add `secureTextEntry`.
66 | - 密文模式.
67 |
68 | ---
69 |
70 | ### 2018-4-19:
71 | 1.`inputBoxSpacing` can be negative.
72 | - 输入框间隔可设置成负数,让输入框连在一起.
73 |
74 | ---
75 |
76 | ### 2017-8-25:
77 | 1.upload.
78 | - 上传.
79 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/JHVerificationCodeView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JHVerificationCodeView
2 | A single authentication code input box
3 | - 单个的验证码输入框
4 |
5 | ---
6 |
7 | # Version
8 | Latest release version:
9 | - [1.3.7](https://github.com/xjh093/JHVerificationCodeView/releases) ❌ out of date!
10 |
11 | - [1.3.8] download master version for use. (2024-05-11 15:06:24)
12 |
13 | Swift version:
14 | - [JHVerifyCodeView](https://github.com/xjh093/JHVerifyCodeView)
15 |
16 | ---
17 |
18 | # Cocoapods
19 |
20 | `pod "JHVerificationCodeView"`
21 |
22 | ---
23 |
24 | # What
25 |
26 | 
27 |
28 | 
29 |
30 | ---
31 |
32 | # Usage
33 |
34 | ```
35 | JHVCConfig *config = [[JHVCConfig alloc] init];
36 | config.inputBoxNumber = 6;
37 | config.inputBoxSpacing = 5;
38 | config.inputBoxWidth = 33;
39 | config.inputBoxHeight = 28;
40 | config.tintColor = [UIColor blackColor];
41 | config.secureTextEntry = YES;
42 | config.inputBoxColor = [UIColor brownColor];
43 | config.font = [UIFont boldSystemFontOfSize:16];
44 | config.textColor = [UIColor brownColor];
45 | config.inputType = JHVCConfigInputType_Number_Alphabet; // Default
46 |
47 | [self.view addSubview:({
48 | JHVerificationCodeView *codeView =
49 | [[JHVerificationCodeView alloc] initWithFrame:CGRectMake(10, 100, kScreenWidth-20, 30)
50 | config:config];
51 | codeView.finishBlock = ^(NSString *code) {
52 | label.text = code;
53 | };
54 | codeView;
55 | })];
56 | ```
57 |
58 | ---
59 |
60 | # Logs
61 |
62 | - change log: [click here](https://github.com/xjh093/JHVerificationCodeView/blob/master/CHANGELOG.md)
63 |
64 | ---
65 |
66 | # More detail in Demo :)
67 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // JHVerificationCodeView
4 | //
5 | // Created by HaoCold on 2017/8/25.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // 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.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // 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.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // 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.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // 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.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/NextViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // NextViewController.m
3 | // JHVerificationCodeView
4 | //
5 | // Created by HaoCold on 2020/9/8.
6 | // Copyright © 2020 HaoCold. All rights reserved.
7 | //
8 |
9 | #import "NextViewController.h"
10 | #import "JHVerificationCodeView.h"
11 |
12 | #define kScreenWidth [UIScreen mainScreen].bounds.size.width
13 | #define kScreenHeight [UIScreen mainScreen].bounds.size.height
14 |
15 | @interface NextViewController ()
16 |
17 | @end
18 |
19 | @implementation NextViewController
20 |
21 | - (void)viewDidLoad {
22 | [super viewDidLoad];
23 | // Do any additional setup after loading the view.
24 |
25 | self.title = @"自动弹出键盘";
26 | self.view.backgroundColor = [UIColor whiteColor];
27 |
28 | [self jhSetupViews];
29 | }
30 |
31 | - (void)jhSetupViews
32 | {
33 | // example 1
34 | {
35 | UILabel *label = [[UILabel alloc] init];
36 | label.frame = CGRectMake(0, 120, kScreenWidth, 30);
37 | label.textAlignment = 1;
38 | label.text = @"InputType: Number & Alphabet";
39 | [self.view addSubview:label];
40 |
41 | JHVCConfig *config = [[JHVCConfig alloc] init];
42 | config.inputBoxNumber = 6;
43 | config.inputBoxSpacing = 5;
44 | config.inputBoxWidth = 33;
45 | config.inputBoxHeight = 28;
46 | config.tintColor = [UIColor blackColor];
47 | config.secureTextEntry = NO;
48 | config.inputBoxColor = [UIColor brownColor];
49 | config.font = [UIFont boldSystemFontOfSize:16];
50 | config.textColor = [UIColor blueColor];
51 | config.inputType = JHVCConfigInputType_Number_Alphabet;
52 |
53 |
54 | config.inputBoxBorderWidth = 1;
55 | config.inputBoxCornerRadius = 5;
56 |
57 | // 自动弹出键盘
58 | config.autoShowKeyboard = YES;
59 | config.autoShowKeyboardDelay = 0.7;
60 |
61 | config.inputBoxFinishColors = @[[UIColor redColor],[UIColor orangeColor]];
62 | config.finishFonts = @[[UIFont boldSystemFontOfSize:20],[UIFont systemFontOfSize:20]];
63 | config.finishTextColors = @[[UIColor greenColor],[UIColor orangeColor]];
64 |
65 | [self.view addSubview:({
66 |
67 | UILabel *label = [[UILabel alloc] init];
68 | label.frame = CGRectMake(0, 180, kScreenWidth, 30);
69 | label.textAlignment = 1;
70 | [self.view addSubview:label];
71 |
72 | JHVerificationCodeView *codeView =
73 | [[JHVerificationCodeView alloc] initWithFrame:CGRectMake(10, 150, kScreenWidth-20, 30)
74 | config:config];
75 | codeView.finishBlock = ^(JHVerificationCodeView *codeView, NSString *code) {
76 | label.text = code;
77 |
78 | // 根据最后输入结果,判断显示哪种颜色
79 | NSUInteger index = [code isEqualToString:@"123asd"] ? 1 : 0;
80 | [codeView showInputFinishColorWithIndex:index];
81 | };
82 | codeView.inputBlock = ^(NSString *code) {
83 | NSLog(@"example 1 code:%@",code);
84 | };
85 | codeView.tag = 100;
86 | codeView;
87 | })];
88 | }
89 | }
90 |
91 |
92 | /*
93 | #pragma mark - Navigation
94 |
95 | // In a storyboard-based application, you will often want to do a little preparation before navigation
96 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
97 | // Get the new view controller using [segue destinationViewController].
98 | // Pass the selected object to the new view controller.
99 | }
100 | */
101 |
102 | @end
103 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/xcuserdata/haocold.xcuserdatad/xcschemes/JHVerificationCodeView.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/JHVerificationCodeView/JHVerificationCodeView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JHVerificationCodeView.h
3 | // JHKit
4 | //
5 | // Created by HaoCold on 2017/8/21.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 | // MIT License
9 | //
10 | // Copyright (c) 2017 xjh093
11 | //
12 | // Permission is hereby granted, free of charge, to any person obtaining a copy
13 | // of this software and associated documentation files (the "Software"), to deal
14 | // in the Software without restriction, including without limitation the rights
15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | // copies of the Software, and to permit persons to whom the Software is
17 | // furnished to do so, subject to the following conditions:
18 | //
19 | // The above copyright notice and this permission notice shall be included in all
20 | // copies or substantial portions of the Software.
21 | //
22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 | // SOFTWARE.
29 |
30 | // version: 1.3.8
31 | // date: 2024-05-11
32 |
33 | #import
34 |
35 | typedef NS_ENUM(NSUInteger, JHVCConfigInputType) {
36 | JHVCConfigInputType_Number_Alphabet,
37 | JHVCConfigInputType_Number,
38 | JHVCConfigInputType_Alphabet,
39 | };
40 |
41 | @interface JHVCConfig : NSObject
42 |
43 | //============================ Initialization ============================
44 |
45 | ///输入框个数
46 | @property (assign, nonatomic) NSInteger inputBoxNumber;
47 | ///单个输入框的宽度
48 | @property (assign, nonatomic) CGFloat inputBoxWidth;
49 | ///单个输入框的高度
50 | @property (assign, nonatomic) CGFloat inputBoxHeight;
51 | ///单个输入框的边框宽度, Default is 1 pixel
52 | @property (assign, nonatomic) CGFloat inputBoxBorderWidth;
53 | ///单个输入框的边框圆角
54 | @property (assign, nonatomic) CGFloat inputBoxCornerRadius;
55 | ///输入框间距, Default is 5
56 | @property (assign, nonatomic) CGFloat inputBoxSpacing;
57 | ///左边距
58 | @property (assign, nonatomic) CGFloat leftMargin;
59 | ///单个输入框的颜色, Default is lightGrayColor
60 | @property (strong, nonatomic) UIColor *inputBoxColor;
61 | ///光标颜色, Default is blueColor
62 | @property (strong, nonatomic) UIColor *tintColor;
63 | ///显示 或 隐藏
64 | @property (assign, nonatomic) BOOL secureTextEntry;
65 | ///字体, Default is [UIFont boldSystemFontOfSize:16]
66 | @property (strong, nonatomic) UIFont *font;
67 | ///颜色, Default is [UIColor blackColor]
68 | @property (strong, nonatomic) UIColor *textColor;
69 | ///输入类型:数字+字母,数字,字母. Default is 'JHVCConfigInputType_Number_Alphabet'
70 | @property (nonatomic, assign) JHVCConfigInputType inputType;
71 | ///自动弹出键盘
72 | @property (nonatomic, assign) BOOL autoShowKeyboard;
73 | ///默认0.5
74 | @property (nonatomic, assign) CGFloat autoShowKeyboardDelay;
75 | ///光标闪烁动画, Default is YES
76 | @property (nonatomic, assign) BOOL showFlickerAnimation;
77 | ///显示下划线
78 | @property (nonatomic, assign) BOOL showUnderLine;
79 | ///下划线尺寸
80 | @property (nonatomic, assign) CGSize underLineSize;
81 | ///下划线颜色, Default is lightGrayColor
82 | @property (nonatomic, strong) UIColor *underLineColor;
83 | ///自定义的输入占位字符,secureTextEntry = NO,有效
84 | @property (nonatomic, copy) NSString *customInputHolder;
85 | ///设置键盘类型
86 | @property (nonatomic, assign) UIKeyboardType keyboardType;
87 | ///使用系统的密码键盘
88 | @property (nonatomic, assign) BOOL useSystemPasswordKeyboard;
89 |
90 | //============================ Input ============================
91 |
92 | ///单个输入框输入时的颜色
93 | @property (strong, nonatomic) UIColor *inputBoxHighlightedColor;
94 | ///下划线高亮颜色
95 | @property (nonatomic, strong) UIColor *underLineHighlightedColor;
96 |
97 | //============================ Finish ============================
98 | /* 输入完成后,可能根据不同的状态,显示不同的颜色。 */
99 |
100 | ///单个输入框输入时的颜色
101 | @property (strong, nonatomic) NSArray *inputBoxFinishColors;
102 | ///下划线高亮颜色
103 | @property (nonatomic, strong) NSArray *underLineFinishColors;
104 | ///输入完成时字体
105 | @property (strong, nonatomic) NSArray *finishFonts;
106 | ///输入完成时颜色
107 | @property (strong, nonatomic) NSArray *finishTextColors;
108 |
109 | @end
110 |
111 | @interface JHVerificationCodeView : UIView
112 |
113 | @property (copy, nonatomic) void (^inputBlock)(NSString *code);
114 | @property (copy, nonatomic) void (^finishBlock)(JHVerificationCodeView *codeView, NSString *code);
115 |
116 | - (instancetype)initWithFrame:(CGRect)frame config:(JHVCConfig *)config;
117 |
118 | /**
119 | 清空所有输入
120 | */
121 | - (void)clear;
122 |
123 | /**
124 | 输入完成后,调用此方法,根据 index 从 `Finish` 下的4个属性获取对应的值来设置颜色。
125 |
126 | @param index 用于从 `inputBoxFinishColors`、`underLineFinishColors`、`finishFonts`、`finishTextColors`中获取对应的值
127 | */
128 | - (void)showInputFinishColorWithIndex:(NSUInteger)index;
129 |
130 | @end
131 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // JHVerificationCodeView
4 | //
5 | // Created by HaoCold on 2017/8/25.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "JHVerificationCodeView.h"
11 | #import "NextViewController.h"
12 |
13 |
14 | #define kScreenWidth [UIScreen mainScreen].bounds.size.width
15 | #define kScreenHeight [UIScreen mainScreen].bounds.size.height
16 |
17 | @interface ViewController ()
18 |
19 | @end
20 |
21 | @implementation ViewController
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | // Do any additional setup after loading the view, typically from a nib.
26 |
27 | self.title = @"验证码输入框";
28 |
29 | [self jhSetupViews];
30 |
31 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:({
32 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
33 | button.titleLabel.font = [UIFont systemFontOfSize:16];
34 | [button setTitle:@"清空" forState:0];
35 | [button setTitleColor:[UIColor blackColor] forState:0];
36 | [button sizeToFit];
37 | [button addTarget:self action:@selector(clearAction) forControlEvents:1<<6];
38 | button;
39 | })];
40 |
41 | self.navigationItem.rightBarButtonItems = @[
42 | [[UIBarButtonItem alloc] initWithCustomView:({
43 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
44 | button.titleLabel.font = [UIFont systemFontOfSize:16];
45 | [button setTitle:@"清空" forState:0];
46 | [button setTitleColor:[UIColor blackColor] forState:0];
47 | [button sizeToFit];
48 | [button addTarget:self action:@selector(clearAction) forControlEvents:1<<6];
49 | button;
50 | })],
51 | [[UIBarButtonItem alloc] initWithCustomView:({
52 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
53 | button.titleLabel.font = [UIFont systemFontOfSize:16];
54 | [button setTitle:@"跳转" forState:0];
55 | [button setTitleColor:[UIColor blackColor] forState:0];
56 | [button sizeToFit];
57 | [button addTarget:self action:@selector(jumpAction) forControlEvents:1<<6];
58 | button;
59 | })]
60 | ];
61 | }
62 |
63 | - (void)jhSetupViews
64 | {
65 | // example 1
66 | {
67 | UILabel *label = [[UILabel alloc] init];
68 | label.frame = CGRectMake(0, 120, kScreenWidth, 30);
69 | label.textAlignment = 1;
70 | label.text = @"InputType: Number & Alphabet";
71 | [self.view addSubview:label];
72 |
73 | JHVCConfig *config = [[JHVCConfig alloc] init];
74 | config.inputBoxNumber = 6;
75 | config.inputBoxSpacing = 5;
76 | config.inputBoxWidth = 33;
77 | config.inputBoxHeight = 28;
78 | config.tintColor = [UIColor blackColor];
79 | config.secureTextEntry = NO;
80 | config.inputBoxColor = [UIColor brownColor];
81 | config.font = [UIFont boldSystemFontOfSize:16];
82 | config.textColor = [UIColor blueColor];
83 | config.inputType = JHVCConfigInputType_Number_Alphabet;
84 |
85 | config.inputBoxBorderWidth = 1;
86 | config.inputBoxCornerRadius = 5;
87 |
88 | //config.customInputHolder = @"🔒";
89 |
90 | config.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
91 | config.useSystemPasswordKeyboard = YES;
92 |
93 | config.inputBoxFinishColors = @[[UIColor redColor],[UIColor orangeColor]];
94 | config.finishFonts = @[[UIFont boldSystemFontOfSize:20],[UIFont systemFontOfSize:20]];
95 | config.finishTextColors = @[[UIColor greenColor],[UIColor orangeColor]];
96 |
97 | [self.view addSubview:({
98 |
99 | UILabel *label = [[UILabel alloc] init];
100 | label.frame = CGRectMake(0, 180, kScreenWidth, 30);
101 | label.textAlignment = 1;
102 | [self.view addSubview:label];
103 |
104 | JHVerificationCodeView *codeView =
105 | [[JHVerificationCodeView alloc] initWithFrame:CGRectMake(10, 150, kScreenWidth-20, 30)
106 | config:config];
107 | codeView.finishBlock = ^(JHVerificationCodeView *codeView, NSString *code) {
108 | label.text = code;
109 |
110 | // 根据最后输入结果,判断显示哪种颜色
111 | NSUInteger index = [code isEqualToString:@"123asd"] ? 1 : 0;
112 | [codeView showInputFinishColorWithIndex:index];
113 | };
114 | codeView.inputBlock = ^(NSString *code) {
115 | NSLog(@"example 1 code:%@",code);
116 | };
117 | codeView.tag = 100;
118 | codeView;
119 | })];
120 | }
121 |
122 | // example 2
123 | {
124 | UILabel *label = [[UILabel alloc] init];
125 | label.frame = CGRectMake(0, 210, kScreenWidth, 30);
126 | label.textAlignment = 1;
127 | label.text = @"InputType: Number";
128 | [self.view addSubview:label];
129 |
130 | JHVCConfig *config = [[JHVCConfig alloc] init];
131 | config.inputBoxNumber = 6;
132 | config.inputBoxSpacing = 5;
133 | config.inputBoxWidth = 33;
134 | config.inputBoxHeight = 28;
135 | config.tintColor = [UIColor greenColor];
136 | config.secureTextEntry = NO;
137 | config.inputBoxColor = [UIColor brownColor];
138 | config.font = [UIFont boldSystemFontOfSize:16];
139 | config.textColor = [UIColor cyanColor];
140 | config.inputType = JHVCConfigInputType_Number;
141 |
142 | config.inputBoxBorderWidth = 1;
143 | config.inputBoxHighlightedColor = [UIColor purpleColor];
144 |
145 | config.customInputHolder = @"🈲";
146 |
147 | config.inputBoxFinishColors = @[[UIColor orangeColor],[UIColor redColor]];
148 | config.finishFonts = @[[UIFont boldSystemFontOfSize:20],[UIFont systemFontOfSize:20]];
149 | config.finishTextColors = @[[UIColor orangeColor],[UIColor greenColor]];
150 |
151 | [self.view addSubview:({
152 |
153 | UILabel *label = [[UILabel alloc] init];
154 | label.frame = CGRectMake(0, 270, kScreenWidth, 30);
155 | label.textAlignment = 1;
156 | [self.view addSubview:label];
157 |
158 | JHVerificationCodeView *codeView =
159 | [[JHVerificationCodeView alloc] initWithFrame:CGRectMake(10, 240, kScreenWidth-20, 30)
160 | config:config];
161 | codeView.finishBlock = ^(JHVerificationCodeView *codeView, NSString *code) {
162 | label.text = code;
163 |
164 | // 根据最后输入结果,判断显示哪种颜色
165 | NSUInteger index = [code isEqualToString:@"123456"] ? 1 : 0;
166 | [codeView showInputFinishColorWithIndex:index];
167 | };
168 | codeView.inputBlock = ^(NSString *code) {
169 | NSLog(@"example 2 code:%@",code);
170 | };
171 | codeView.tag = 200;
172 | codeView;
173 | })];
174 | }
175 |
176 | // example 3
177 | {
178 | UILabel *label = [[UILabel alloc] init];
179 | label.frame = CGRectMake(0, 300, kScreenWidth, 30);
180 | label.textAlignment = 1;
181 | label.text = @"InputType: Alphabet";
182 | [self.view addSubview:label];
183 |
184 | JHVCConfig *config = [[JHVCConfig alloc] init];
185 | config.inputBoxNumber = 6;
186 | config.inputBoxSpacing = -1;
187 | config.inputBoxWidth = 33;
188 | config.inputBoxHeight = 28;
189 | config.tintColor = [UIColor redColor];
190 | config.secureTextEntry = NO;
191 | config.inputBoxColor = [UIColor brownColor];
192 | config.font = [UIFont boldSystemFontOfSize:16];
193 | config.textColor = [UIColor grayColor];
194 | config.inputType = JHVCConfigInputType_Alphabet;
195 |
196 | config.inputBoxBorderWidth = 1;
197 |
198 | config.customInputHolder = @"❄️";
199 |
200 | [self.view addSubview:({
201 |
202 | UILabel *label = [[UILabel alloc] init];
203 | label.frame = CGRectMake(0, 360, kScreenWidth, 30);
204 | label.textAlignment = 1;
205 | [self.view addSubview:label];
206 |
207 | JHVerificationCodeView *codeView =
208 | [[JHVerificationCodeView alloc] initWithFrame:CGRectMake(10, 330, kScreenWidth-20, 30)
209 | config:config];
210 | codeView.finishBlock = ^(JHVerificationCodeView *codeView, NSString *code) {
211 | label.text = code;
212 | };
213 | codeView.inputBlock = ^(NSString *code) {
214 | NSLog(@"example 3 code:%@",code);
215 | };
216 | codeView.tag = 300;
217 | codeView;
218 | })];
219 | }
220 |
221 | // example 4
222 | {
223 | UILabel *label = [[UILabel alloc] init];
224 | label.frame = CGRectMake(0, 390, kScreenWidth, 30);
225 | label.textAlignment = 1;
226 | label.text = @"InputType: Alphabet";
227 | [self.view addSubview:label];
228 |
229 | JHVCConfig *config = [[JHVCConfig alloc] init];
230 | config.inputBoxNumber = 4;
231 | config.inputBoxSpacing = 4;
232 | config.inputBoxWidth = 33;
233 | config.inputBoxHeight = 28;
234 | config.tintColor = [UIColor blueColor];
235 | config.secureTextEntry = YES;
236 | config.inputBoxColor = [UIColor clearColor];
237 | config.font = [UIFont boldSystemFontOfSize:20];
238 | config.textColor = [UIColor grayColor];
239 | config.inputType = JHVCConfigInputType_Alphabet;
240 |
241 | config.inputBoxBorderWidth = 1;
242 | config.showUnderLine = YES;
243 | config.underLineSize = CGSizeMake(33, 2);
244 | config.underLineColor = [UIColor brownColor];
245 | config.underLineHighlightedColor = [UIColor redColor];
246 |
247 | config.underLineFinishColors = @[[UIColor blueColor],[UIColor orangeColor]];
248 | config.finishFonts = @[[UIFont boldSystemFontOfSize:20],[UIFont systemFontOfSize:20]];
249 | config.finishTextColors = @[[UIColor greenColor],[UIColor orangeColor]];
250 |
251 | [self.view addSubview:({
252 |
253 | UILabel *label = [[UILabel alloc] init];
254 | label.frame = CGRectMake(0, 450, kScreenWidth, 30);
255 | label.textAlignment = 1;
256 | [self.view addSubview:label];
257 |
258 | JHVerificationCodeView *codeView =
259 | [[JHVerificationCodeView alloc] initWithFrame:CGRectMake(10, 420, kScreenWidth-20, 30)
260 | config:config];
261 | codeView.finishBlock = ^(JHVerificationCodeView *codeView, NSString *code) {
262 | label.text = code;
263 |
264 | // 根据最后输入结果,判断显示哪种颜色
265 | NSUInteger index = [code isEqualToString:@"Asdf"] ? 1 : 0;
266 | [codeView showInputFinishColorWithIndex:index];
267 | };
268 | codeView.inputBlock = ^(NSString *code) {
269 | NSLog(@"example 4 code:%@",code);
270 | };
271 | codeView.tag = 400;
272 | codeView;
273 | })];
274 | }
275 | }
276 |
277 |
278 | - (void)clearAction
279 | {
280 | JHVerificationCodeView *codeView1 = [self.view viewWithTag:100];
281 | JHVerificationCodeView *codeView2 = [self.view viewWithTag:200];
282 | JHVerificationCodeView *codeView3 = [self.view viewWithTag:300];
283 | JHVerificationCodeView *codeView4 = [self.view viewWithTag:400];
284 |
285 | [codeView1 clear];
286 | [codeView2 clear];
287 | [codeView3 clear];
288 | [codeView4 clear];
289 |
290 | }
291 |
292 | - (void)jumpAction
293 | {
294 | [self.navigationController pushViewController:[[NextViewController alloc] init] animated:YES];
295 | }
296 |
297 | - (void)didReceiveMemoryWarning {
298 | [super didReceiveMemoryWarning];
299 | // Dispose of any resources that can be recreated.
300 | }
301 |
302 |
303 | @end
304 |
--------------------------------------------------------------------------------
/JHVerificationCodeView/JHVerificationCodeView/JHVerificationCodeView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JHVerificationCodeView.m
3 | // JHKit
4 | //
5 | // Created by HaoCold on 2017/8/21.
6 | // Copyright © 2017年 HaoCold. All rights reserved.
7 | //
8 | // MIT License
9 | //
10 | // Copyright (c) 2017 xjh093
11 | //
12 | // Permission is hereby granted, free of charge, to any person obtaining a copy
13 | // of this software and associated documentation files (the "Software"), to deal
14 | // in the Software without restriction, including without limitation the rights
15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | // copies of the Software, and to permit persons to whom the Software is
17 | // furnished to do so, subject to the following conditions:
18 | //
19 | // The above copyright notice and this permission notice shall be included in all
20 | // copies or substantial portions of the Software.
21 | //
22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 | // SOFTWARE.
29 |
30 | #import "JHVerificationCodeView.h"
31 |
32 | #define kFlickerAnimation @"kFlickerAnimation"
33 |
34 | @implementation JHVCConfig
35 |
36 | - (instancetype)init{
37 | if (self = [super init]) {
38 | _inputBoxBorderWidth = 1.0/[UIScreen mainScreen].scale;
39 | _inputBoxSpacing = 5;
40 | _inputBoxColor = [UIColor lightGrayColor];
41 | _tintColor = [UIColor blueColor];
42 | _font = [UIFont boldSystemFontOfSize:16];
43 | _textColor = [UIColor blackColor];
44 | _showFlickerAnimation = YES;
45 | _underLineColor = [UIColor lightGrayColor];
46 | _autoShowKeyboardDelay = 0.5;
47 | }
48 | return self;
49 | }
50 |
51 | @end
52 |
53 | @interface JHVerificationCodeView()
54 | @property (strong, nonatomic) JHVCConfig *config;
55 | @property (strong, nonatomic) UITextField *textView;
56 | @property (nonatomic, assign) BOOL inputFinish;
57 | @property (nonatomic, assign) NSUInteger inputFinishIndex;
58 | /// 存放光标 layer --- 2024-05-11 14:44:14
59 | @property (nonatomic, strong) NSMutableArray *layerArray;
60 | @end
61 |
62 | @implementation JHVerificationCodeView
63 |
64 | - (void)dealloc{
65 | [[NSNotificationCenter defaultCenter] removeObserver:self];
66 | }
67 |
68 | - (instancetype)initWithFrame:(CGRect)frame config:(JHVCConfig *)config{
69 | if (self = [super initWithFrame:frame]) {
70 | _config = config;
71 | [self jhSetupViews:frame];
72 | }
73 | return self;
74 | }
75 |
76 | - (void)jhSetupViews:(CGRect)frame
77 | {
78 | if (frame.size.width <= 0 ||
79 | frame.size.height <= 0 ||
80 | _config.inputBoxNumber == 0 ||
81 | _config.inputBoxWidth > frame.size.width) {
82 | return;
83 | }
84 |
85 | _layerArray = @[].mutableCopy;
86 |
87 | //优先考虑 inputBoxWidth
88 | CGFloat inputBoxSpacing = _config.inputBoxSpacing;
89 |
90 | CGFloat inputBoxWidth = 0;
91 | if (_config.inputBoxWidth > 0) {
92 | inputBoxWidth = _config.inputBoxWidth;
93 | }
94 |
95 | CGFloat leftMargin = 0;
96 | if (inputBoxWidth > 0) {
97 | _config.leftMargin = (CGRectGetWidth(frame)-inputBoxWidth*_config.inputBoxNumber-inputBoxSpacing*(_config.inputBoxNumber-1))*0.5;
98 | leftMargin = _config.leftMargin;
99 | }else{
100 | _config.inputBoxWidth = (CGRectGetWidth(frame)-inputBoxSpacing*(_config.inputBoxNumber-1)-_config.leftMargin*2)/_config.inputBoxNumber;
101 | inputBoxWidth = _config.inputBoxWidth;
102 | }
103 |
104 | if (_config.leftMargin < 0) {
105 | _config.leftMargin = 0;
106 | _config.inputBoxWidth = (CGRectGetWidth(frame)-inputBoxSpacing*(_config.inputBoxNumber-1)-_config.leftMargin*2)/_config.inputBoxNumber;
107 |
108 | leftMargin = _config.leftMargin;
109 | inputBoxWidth = _config.inputBoxWidth;
110 | }
111 |
112 | CGFloat inputBoxHeight = 0;
113 | if (_config.inputBoxHeight > CGRectGetHeight(frame)) {
114 | _config.inputBoxHeight = CGRectGetHeight(frame);
115 | }
116 | inputBoxHeight = _config.inputBoxHeight;
117 |
118 | if (_config.showUnderLine) {
119 | if (_config.underLineSize.width <= 0) {
120 | CGSize size = _config.underLineSize;
121 | size.width = inputBoxWidth;
122 | _config.underLineSize = size;
123 | }
124 | if (_config.underLineSize.height <= 0) {
125 | CGSize size = _config.underLineSize;
126 | size.height = 1;
127 | _config.underLineSize = size;
128 | }
129 | }
130 |
131 | for (int i = 0; i < _config.inputBoxNumber; ++i) {
132 | UITextField *textField = [[UITextField alloc] init];
133 | textField.frame = CGRectMake(_config.leftMargin+(inputBoxWidth+inputBoxSpacing)*i, (CGRectGetHeight(frame)-inputBoxHeight)*0.5, inputBoxWidth, inputBoxHeight);
134 | textField.textAlignment = 1;
135 | if (_config.inputBoxBorderWidth) {
136 | textField.layer.borderWidth = _config.inputBoxBorderWidth;
137 | }
138 | if (_config.inputBoxCornerRadius) {
139 | textField.layer.cornerRadius = _config.inputBoxCornerRadius;
140 | }
141 | if (_config.inputBoxColor) {
142 | textField.layer.borderColor = _config.inputBoxColor.CGColor;
143 | }
144 | if (_config.tintColor) {
145 | if (inputBoxWidth > 2 && inputBoxHeight > 8) {
146 | CGFloat w = 2, y = 4, x = (inputBoxWidth-w)/2, h = inputBoxHeight-2*y;
147 | [textField.layer addSublayer:({
148 | UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(x,y,w,h)];
149 | CAShapeLayer *layer = [CAShapeLayer layer];
150 | layer.path = path.CGPath;
151 | layer.fillColor = _config.tintColor.CGColor;
152 | [layer addAnimation:[self xx_alphaAnimation] forKey:kFlickerAnimation];
153 | if (i != 0) {
154 | layer.hidden = YES;
155 | }
156 |
157 | [_layerArray addObject:layer];
158 | layer;
159 | })];
160 | }
161 | }
162 | if (_config.secureTextEntry) {
163 | textField.secureTextEntry = _config.secureTextEntry;
164 | }
165 | if (_config.font){
166 | textField.font = _config.font;
167 | }
168 | if (_config.textColor) {
169 | textField.textColor = _config.textColor;
170 | }
171 | if (_config.showUnderLine) {
172 | CGFloat x = (inputBoxWidth-_config.underLineSize.width)/2.0;
173 | CGFloat y = (inputBoxHeight-_config.underLineSize.height);
174 | CGRect frame = CGRectMake(x, y, _config.underLineSize.width, _config.underLineSize.height);
175 |
176 | UIView *underLine = [[UIView alloc] init];
177 | underLine.tag = 100;
178 | underLine.frame = frame;
179 | underLine.backgroundColor = _config.underLineColor;
180 | [textField addSubview:underLine];
181 |
182 | }
183 |
184 | textField.tag = i;
185 | textField.userInteractionEnabled = NO;
186 | [self addSubview:textField];
187 | }
188 |
189 | [self addGestureRecognizer:({
190 | [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(xx_tap)];
191 | })];
192 |
193 | _textView = [[UITextField alloc] init];
194 | _textView.frame = CGRectMake(0, CGRectGetHeight(frame), 0, 0);
195 | _textView.secureTextEntry = _config.useSystemPasswordKeyboard;
196 | _textView.keyboardType = _config.keyboardType;
197 | _textView.hidden = YES;
198 | if (@available(iOS 12.0, *)) {
199 | _textView.textContentType = UITextContentTypeOneTimeCode;
200 | }
201 | [self addSubview:_textView];
202 |
203 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(xx_textChange:) name:UITextFieldTextDidChangeNotification object:_textView];
204 | //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(xx_didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
205 |
206 | if (_config.autoShowKeyboard) {
207 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_config.autoShowKeyboardDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
208 | [_textView becomeFirstResponder];
209 | });
210 | }
211 | }
212 |
213 | - (CABasicAnimation *)xx_alphaAnimation{
214 | CABasicAnimation *alpha = [CABasicAnimation animationWithKeyPath:@"opacity"];
215 | alpha.fromValue = @(1.0);
216 | alpha.toValue = @(0.0);
217 | alpha.duration = 1.0;
218 | alpha.repeatCount = CGFLOAT_MAX;
219 | alpha.removedOnCompletion = NO;
220 | alpha.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
221 | return alpha;
222 | }
223 |
224 | - (void)xx_tap{
225 | [_textView becomeFirstResponder];
226 | }
227 |
228 | - (void)xx_didBecomeActive{
229 | // restart Flicker Animation
230 | if (_config.showFlickerAnimation && _textView.text.length < _layerArray.count) {
231 | CALayer *layer = _layerArray[_textView.text.length];
232 | [layer removeAnimationForKey:kFlickerAnimation];
233 | [layer addAnimation:[self xx_alphaAnimation] forKey:kFlickerAnimation];
234 | }
235 | }
236 |
237 | - (void)xx_textChange:(NSNotification *)noti
238 | {
239 | //NSLog(@"%@",noti.object);
240 | if (_textView != noti.object) {
241 | return;
242 | }
243 |
244 | // set default
245 | [self xx_setDefault];
246 |
247 | // trim space
248 | NSString *text = [_textView.text stringByReplacingOccurrencesOfString:@" " withString:@""];
249 |
250 | // number & alphabet
251 | NSMutableString *mstr = @"".mutableCopy;
252 | for (int i = 0; i < text.length; ++i) {
253 | unichar c = [text characterAtIndex:i];
254 | if (_config.inputType == JHVCConfigInputType_Number_Alphabet) {
255 | if ((c >= '0' && c <= '9') ||
256 | (c >= 'A' && c <= 'Z') ||
257 | (c >= 'a' && c <= 'z')) {
258 | [mstr appendFormat:@"%c",c];
259 | }
260 | }else if (_config.inputType == JHVCConfigInputType_Number) {
261 | if ((c >= '0' && c <= '9')) {
262 | [mstr appendFormat:@"%c",c];
263 | }
264 | }else if (_config.inputType == JHVCConfigInputType_Alphabet) {
265 | if ((c >= 'A' && c <= 'Z') ||
266 | (c >= 'a' && c <= 'z')) {
267 | [mstr appendFormat:@"%c",c];
268 | }
269 | }
270 | }
271 |
272 | text = mstr;
273 | NSInteger count = _config.inputBoxNumber;
274 | if (text.length > count) {
275 | text = [text substringToIndex:count];
276 | }
277 | _textView.text = text;
278 | if (_inputBlock) {
279 | _inputBlock(text);
280 | }
281 |
282 | // set value
283 | [self xx_setValue:text];
284 |
285 | // Flicker Animation
286 | [self xx_flickerAnimation:text];
287 |
288 | if (_inputFinish) {
289 | [self xx_finish];
290 | }
291 | }
292 |
293 | - (void)xx_setDefault
294 | {
295 | for (int i = 0; i < _config.inputBoxNumber; ++i) {
296 | UITextField *textField = self.subviews[i];
297 | textField.text = @"";
298 |
299 | if (_config.inputBoxColor) {
300 | textField.layer.borderColor = _config.inputBoxColor.CGColor;
301 | }
302 | if (_config.showFlickerAnimation && _layerArray.count > i) {
303 | CALayer *layer = _layerArray[i];
304 | layer.hidden = YES;
305 | [layer removeAnimationForKey:kFlickerAnimation];
306 | }
307 | if (_config.showUnderLine) {
308 | UIView *underLine = [textField viewWithTag:100];
309 | underLine.backgroundColor = _config.underLineColor;
310 | }
311 | }
312 | }
313 |
314 | - (void)xx_flickerAnimation:(NSString *)text
315 | {
316 | if (_config.showFlickerAnimation && text.length < _layerArray.count) {
317 | CALayer *layer = _layerArray[text.length];
318 | layer.hidden = NO;
319 | [layer addAnimation:[self xx_alphaAnimation] forKey:kFlickerAnimation];
320 | }
321 | }
322 |
323 | - (void)xx_setValue:(NSString *)text
324 | {
325 | _inputFinish = (text.length == _config.inputBoxNumber);
326 |
327 | for (int i = 0; i < text.length; ++i) {
328 | unichar c = [text characterAtIndex:i];
329 | UITextField *textField = self.subviews[i];
330 | textField.text = [NSString stringWithFormat:@"%c",c];
331 | if (!textField.secureTextEntry && _config.customInputHolder.length > 0) {
332 | textField.text = _config.customInputHolder;
333 | }
334 |
335 | // Input Status
336 | UIFont *font = _config.font;
337 | UIColor *color = _config.textColor;
338 | UIColor *inputBoxColor = _config.inputBoxHighlightedColor;
339 | UIColor *underLineColor = _config.underLineHighlightedColor;
340 |
341 | // Finish Status
342 | if (_inputFinish) {
343 | if (_inputFinishIndex < _config.finishFonts.count) {
344 | font = _config.finishFonts[_inputFinishIndex];
345 | }
346 | if (_inputFinishIndex < _config.finishTextColors.count) {
347 | color = _config.finishTextColors[_inputFinishIndex];
348 | }
349 | if (_inputFinishIndex < _config.inputBoxFinishColors.count) {
350 | inputBoxColor = _config.inputBoxFinishColors[_inputFinishIndex];
351 | }
352 | if (_inputFinishIndex < _config.underLineFinishColors.count) {
353 | underLineColor = _config.underLineFinishColors[_inputFinishIndex];
354 | }
355 | }
356 |
357 | textField.font = font;
358 | textField.textColor = color;
359 |
360 | if (inputBoxColor) {
361 | textField.layer.borderColor = inputBoxColor.CGColor;
362 | }
363 | if (_config.showUnderLine && underLineColor) {
364 | UIView *underLine = [textField viewWithTag:100];
365 | underLine.backgroundColor = underLineColor;
366 | }
367 | }
368 | }
369 |
370 | - (void)xx_finish
371 | {
372 | if (_finishBlock) {
373 | _finishBlock(self, _textView.text);
374 | }
375 |
376 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
377 | [self endEditing:YES];
378 | });
379 | }
380 |
381 | #pragma mark - public
382 |
383 | - (void)clear
384 | {
385 | _textView.text = @"";
386 |
387 | [self xx_setDefault];
388 | [self xx_flickerAnimation:_textView.text];
389 | }
390 |
391 | - (void)showInputFinishColorWithIndex:(NSUInteger)index
392 | {
393 | _inputFinishIndex = index;
394 |
395 | [self xx_setValue:_textView.text];
396 | }
397 |
398 | @end
399 |
--------------------------------------------------------------------------------
/JHVerificationCodeView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 088BF8AC1F4FAF3C00B5863B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 088BF8AB1F4FAF3C00B5863B /* main.m */; };
11 | 088BF8AF1F4FAF3C00B5863B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 088BF8AE1F4FAF3C00B5863B /* AppDelegate.m */; };
12 | 088BF8B21F4FAF3C00B5863B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 088BF8B11F4FAF3C00B5863B /* ViewController.m */; };
13 | 088BF8B51F4FAF3C00B5863B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 088BF8B31F4FAF3C00B5863B /* Main.storyboard */; };
14 | 088BF8B71F4FAF3C00B5863B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 088BF8B61F4FAF3C00B5863B /* Assets.xcassets */; };
15 | 088BF8BA1F4FAF3C00B5863B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 088BF8B81F4FAF3C00B5863B /* LaunchScreen.storyboard */; };
16 | 088BF8C51F4FAF3C00B5863B /* JHVerificationCodeViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 088BF8C41F4FAF3C00B5863B /* JHVerificationCodeViewTests.m */; };
17 | 088BF8D21F4FAF7500B5863B /* JHVerificationCodeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 088BF8D11F4FAF7500B5863B /* JHVerificationCodeView.m */; };
18 | 18EE78502507AA8000E7F10D /* NextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EE784F2507AA8000E7F10D /* NextViewController.m */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXContainerItemProxy section */
22 | 088BF8C11F4FAF3C00B5863B /* PBXContainerItemProxy */ = {
23 | isa = PBXContainerItemProxy;
24 | containerPortal = 088BF89F1F4FAF3C00B5863B /* Project object */;
25 | proxyType = 1;
26 | remoteGlobalIDString = 088BF8A61F4FAF3C00B5863B;
27 | remoteInfo = JHVerificationCodeView;
28 | };
29 | /* End PBXContainerItemProxy section */
30 |
31 | /* Begin PBXFileReference section */
32 | 088BF8A71F4FAF3C00B5863B /* JHVerificationCodeView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JHVerificationCodeView.app; sourceTree = BUILT_PRODUCTS_DIR; };
33 | 088BF8AB1F4FAF3C00B5863B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
34 | 088BF8AD1F4FAF3C00B5863B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
35 | 088BF8AE1F4FAF3C00B5863B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
36 | 088BF8B01F4FAF3C00B5863B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
37 | 088BF8B11F4FAF3C00B5863B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
38 | 088BF8B41F4FAF3C00B5863B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
39 | 088BF8B61F4FAF3C00B5863B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
40 | 088BF8B91F4FAF3C00B5863B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
41 | 088BF8BB1F4FAF3C00B5863B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
42 | 088BF8C01F4FAF3C00B5863B /* JHVerificationCodeViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JHVerificationCodeViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
43 | 088BF8C41F4FAF3C00B5863B /* JHVerificationCodeViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JHVerificationCodeViewTests.m; sourceTree = ""; };
44 | 088BF8C61F4FAF3C00B5863B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | 088BF8D01F4FAF7500B5863B /* JHVerificationCodeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JHVerificationCodeView.h; sourceTree = ""; };
46 | 088BF8D11F4FAF7500B5863B /* JHVerificationCodeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JHVerificationCodeView.m; sourceTree = ""; };
47 | 18EE784E2507AA8000E7F10D /* NextViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NextViewController.h; sourceTree = ""; };
48 | 18EE784F2507AA8000E7F10D /* NextViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NextViewController.m; sourceTree = ""; };
49 | /* End PBXFileReference section */
50 |
51 | /* Begin PBXFrameworksBuildPhase section */
52 | 088BF8A41F4FAF3C00B5863B /* Frameworks */ = {
53 | isa = PBXFrameworksBuildPhase;
54 | buildActionMask = 2147483647;
55 | files = (
56 | );
57 | runOnlyForDeploymentPostprocessing = 0;
58 | };
59 | 088BF8BD1F4FAF3C00B5863B /* Frameworks */ = {
60 | isa = PBXFrameworksBuildPhase;
61 | buildActionMask = 2147483647;
62 | files = (
63 | );
64 | runOnlyForDeploymentPostprocessing = 0;
65 | };
66 | /* End PBXFrameworksBuildPhase section */
67 |
68 | /* Begin PBXGroup section */
69 | 088BF89E1F4FAF3C00B5863B = {
70 | isa = PBXGroup;
71 | children = (
72 | 088BF8A91F4FAF3C00B5863B /* JHVerificationCodeView */,
73 | 088BF8C31F4FAF3C00B5863B /* JHVerificationCodeViewTests */,
74 | 088BF8A81F4FAF3C00B5863B /* Products */,
75 | );
76 | sourceTree = "";
77 | };
78 | 088BF8A81F4FAF3C00B5863B /* Products */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 088BF8A71F4FAF3C00B5863B /* JHVerificationCodeView.app */,
82 | 088BF8C01F4FAF3C00B5863B /* JHVerificationCodeViewTests.xctest */,
83 | );
84 | name = Products;
85 | sourceTree = "";
86 | };
87 | 088BF8A91F4FAF3C00B5863B /* JHVerificationCodeView */ = {
88 | isa = PBXGroup;
89 | children = (
90 | 088BF8CF1F4FAF7500B5863B /* JHVerificationCodeView */,
91 | 088BF8AD1F4FAF3C00B5863B /* AppDelegate.h */,
92 | 088BF8AE1F4FAF3C00B5863B /* AppDelegate.m */,
93 | 088BF8B01F4FAF3C00B5863B /* ViewController.h */,
94 | 088BF8B11F4FAF3C00B5863B /* ViewController.m */,
95 | 18EE784E2507AA8000E7F10D /* NextViewController.h */,
96 | 18EE784F2507AA8000E7F10D /* NextViewController.m */,
97 | 088BF8B31F4FAF3C00B5863B /* Main.storyboard */,
98 | 088BF8B61F4FAF3C00B5863B /* Assets.xcassets */,
99 | 088BF8B81F4FAF3C00B5863B /* LaunchScreen.storyboard */,
100 | 088BF8BB1F4FAF3C00B5863B /* Info.plist */,
101 | 088BF8AA1F4FAF3C00B5863B /* Supporting Files */,
102 | );
103 | path = JHVerificationCodeView;
104 | sourceTree = "";
105 | };
106 | 088BF8AA1F4FAF3C00B5863B /* Supporting Files */ = {
107 | isa = PBXGroup;
108 | children = (
109 | 088BF8AB1F4FAF3C00B5863B /* main.m */,
110 | );
111 | name = "Supporting Files";
112 | sourceTree = "";
113 | };
114 | 088BF8C31F4FAF3C00B5863B /* JHVerificationCodeViewTests */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 088BF8C41F4FAF3C00B5863B /* JHVerificationCodeViewTests.m */,
118 | 088BF8C61F4FAF3C00B5863B /* Info.plist */,
119 | );
120 | path = JHVerificationCodeViewTests;
121 | sourceTree = "";
122 | };
123 | 088BF8CF1F4FAF7500B5863B /* JHVerificationCodeView */ = {
124 | isa = PBXGroup;
125 | children = (
126 | 088BF8D01F4FAF7500B5863B /* JHVerificationCodeView.h */,
127 | 088BF8D11F4FAF7500B5863B /* JHVerificationCodeView.m */,
128 | );
129 | path = JHVerificationCodeView;
130 | sourceTree = "";
131 | };
132 | /* End PBXGroup section */
133 |
134 | /* Begin PBXNativeTarget section */
135 | 088BF8A61F4FAF3C00B5863B /* JHVerificationCodeView */ = {
136 | isa = PBXNativeTarget;
137 | buildConfigurationList = 088BF8C91F4FAF3C00B5863B /* Build configuration list for PBXNativeTarget "JHVerificationCodeView" */;
138 | buildPhases = (
139 | 088BF8A31F4FAF3C00B5863B /* Sources */,
140 | 088BF8A41F4FAF3C00B5863B /* Frameworks */,
141 | 088BF8A51F4FAF3C00B5863B /* Resources */,
142 | );
143 | buildRules = (
144 | );
145 | dependencies = (
146 | );
147 | name = JHVerificationCodeView;
148 | productName = JHVerificationCodeView;
149 | productReference = 088BF8A71F4FAF3C00B5863B /* JHVerificationCodeView.app */;
150 | productType = "com.apple.product-type.application";
151 | };
152 | 088BF8BF1F4FAF3C00B5863B /* JHVerificationCodeViewTests */ = {
153 | isa = PBXNativeTarget;
154 | buildConfigurationList = 088BF8CC1F4FAF3C00B5863B /* Build configuration list for PBXNativeTarget "JHVerificationCodeViewTests" */;
155 | buildPhases = (
156 | 088BF8BC1F4FAF3C00B5863B /* Sources */,
157 | 088BF8BD1F4FAF3C00B5863B /* Frameworks */,
158 | 088BF8BE1F4FAF3C00B5863B /* Resources */,
159 | );
160 | buildRules = (
161 | );
162 | dependencies = (
163 | 088BF8C21F4FAF3C00B5863B /* PBXTargetDependency */,
164 | );
165 | name = JHVerificationCodeViewTests;
166 | productName = JHVerificationCodeViewTests;
167 | productReference = 088BF8C01F4FAF3C00B5863B /* JHVerificationCodeViewTests.xctest */;
168 | productType = "com.apple.product-type.bundle.unit-test";
169 | };
170 | /* End PBXNativeTarget section */
171 |
172 | /* Begin PBXProject section */
173 | 088BF89F1F4FAF3C00B5863B /* Project object */ = {
174 | isa = PBXProject;
175 | attributes = {
176 | LastUpgradeCheck = 0830;
177 | ORGANIZATIONNAME = HaoCold;
178 | TargetAttributes = {
179 | 088BF8A61F4FAF3C00B5863B = {
180 | CreatedOnToolsVersion = 8.3.2;
181 | DevelopmentTeam = D8MERC5W3E;
182 | ProvisioningStyle = Manual;
183 | };
184 | 088BF8BF1F4FAF3C00B5863B = {
185 | CreatedOnToolsVersion = 8.3.2;
186 | ProvisioningStyle = Automatic;
187 | TestTargetID = 088BF8A61F4FAF3C00B5863B;
188 | };
189 | };
190 | };
191 | buildConfigurationList = 088BF8A21F4FAF3C00B5863B /* Build configuration list for PBXProject "JHVerificationCodeView" */;
192 | compatibilityVersion = "Xcode 3.2";
193 | developmentRegion = English;
194 | hasScannedForEncodings = 0;
195 | knownRegions = (
196 | English,
197 | en,
198 | Base,
199 | );
200 | mainGroup = 088BF89E1F4FAF3C00B5863B;
201 | productRefGroup = 088BF8A81F4FAF3C00B5863B /* Products */;
202 | projectDirPath = "";
203 | projectRoot = "";
204 | targets = (
205 | 088BF8A61F4FAF3C00B5863B /* JHVerificationCodeView */,
206 | 088BF8BF1F4FAF3C00B5863B /* JHVerificationCodeViewTests */,
207 | );
208 | };
209 | /* End PBXProject section */
210 |
211 | /* Begin PBXResourcesBuildPhase section */
212 | 088BF8A51F4FAF3C00B5863B /* Resources */ = {
213 | isa = PBXResourcesBuildPhase;
214 | buildActionMask = 2147483647;
215 | files = (
216 | 088BF8BA1F4FAF3C00B5863B /* LaunchScreen.storyboard in Resources */,
217 | 088BF8B71F4FAF3C00B5863B /* Assets.xcassets in Resources */,
218 | 088BF8B51F4FAF3C00B5863B /* Main.storyboard in Resources */,
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | };
222 | 088BF8BE1F4FAF3C00B5863B /* Resources */ = {
223 | isa = PBXResourcesBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | );
227 | runOnlyForDeploymentPostprocessing = 0;
228 | };
229 | /* End PBXResourcesBuildPhase section */
230 |
231 | /* Begin PBXSourcesBuildPhase section */
232 | 088BF8A31F4FAF3C00B5863B /* Sources */ = {
233 | isa = PBXSourcesBuildPhase;
234 | buildActionMask = 2147483647;
235 | files = (
236 | 18EE78502507AA8000E7F10D /* NextViewController.m in Sources */,
237 | 088BF8B21F4FAF3C00B5863B /* ViewController.m in Sources */,
238 | 088BF8AF1F4FAF3C00B5863B /* AppDelegate.m in Sources */,
239 | 088BF8D21F4FAF7500B5863B /* JHVerificationCodeView.m in Sources */,
240 | 088BF8AC1F4FAF3C00B5863B /* main.m in Sources */,
241 | );
242 | runOnlyForDeploymentPostprocessing = 0;
243 | };
244 | 088BF8BC1F4FAF3C00B5863B /* Sources */ = {
245 | isa = PBXSourcesBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | 088BF8C51F4FAF3C00B5863B /* JHVerificationCodeViewTests.m in Sources */,
249 | );
250 | runOnlyForDeploymentPostprocessing = 0;
251 | };
252 | /* End PBXSourcesBuildPhase section */
253 |
254 | /* Begin PBXTargetDependency section */
255 | 088BF8C21F4FAF3C00B5863B /* PBXTargetDependency */ = {
256 | isa = PBXTargetDependency;
257 | target = 088BF8A61F4FAF3C00B5863B /* JHVerificationCodeView */;
258 | targetProxy = 088BF8C11F4FAF3C00B5863B /* PBXContainerItemProxy */;
259 | };
260 | /* End PBXTargetDependency section */
261 |
262 | /* Begin PBXVariantGroup section */
263 | 088BF8B31F4FAF3C00B5863B /* Main.storyboard */ = {
264 | isa = PBXVariantGroup;
265 | children = (
266 | 088BF8B41F4FAF3C00B5863B /* Base */,
267 | );
268 | name = Main.storyboard;
269 | sourceTree = "";
270 | };
271 | 088BF8B81F4FAF3C00B5863B /* LaunchScreen.storyboard */ = {
272 | isa = PBXVariantGroup;
273 | children = (
274 | 088BF8B91F4FAF3C00B5863B /* Base */,
275 | );
276 | name = LaunchScreen.storyboard;
277 | sourceTree = "";
278 | };
279 | /* End PBXVariantGroup section */
280 |
281 | /* Begin XCBuildConfiguration section */
282 | 088BF8C71F4FAF3C00B5863B /* Debug */ = {
283 | isa = XCBuildConfiguration;
284 | buildSettings = {
285 | ALWAYS_SEARCH_USER_PATHS = NO;
286 | CLANG_ANALYZER_NONNULL = YES;
287 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
288 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
289 | CLANG_CXX_LIBRARY = "libc++";
290 | CLANG_ENABLE_MODULES = YES;
291 | CLANG_ENABLE_OBJC_ARC = YES;
292 | CLANG_WARN_BOOL_CONVERSION = YES;
293 | CLANG_WARN_CONSTANT_CONVERSION = YES;
294 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
295 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
296 | CLANG_WARN_EMPTY_BODY = YES;
297 | CLANG_WARN_ENUM_CONVERSION = YES;
298 | CLANG_WARN_INFINITE_RECURSION = YES;
299 | CLANG_WARN_INT_CONVERSION = YES;
300 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
301 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
302 | CLANG_WARN_UNREACHABLE_CODE = YES;
303 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
304 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
305 | COPY_PHASE_STRIP = NO;
306 | DEBUG_INFORMATION_FORMAT = dwarf;
307 | ENABLE_STRICT_OBJC_MSGSEND = YES;
308 | ENABLE_TESTABILITY = YES;
309 | GCC_C_LANGUAGE_STANDARD = gnu99;
310 | GCC_DYNAMIC_NO_PIC = NO;
311 | GCC_NO_COMMON_BLOCKS = YES;
312 | GCC_OPTIMIZATION_LEVEL = 0;
313 | GCC_PREPROCESSOR_DEFINITIONS = (
314 | "DEBUG=1",
315 | "$(inherited)",
316 | );
317 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
318 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
319 | GCC_WARN_UNDECLARED_SELECTOR = YES;
320 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
321 | GCC_WARN_UNUSED_FUNCTION = YES;
322 | GCC_WARN_UNUSED_VARIABLE = YES;
323 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
324 | MTL_ENABLE_DEBUG_INFO = YES;
325 | ONLY_ACTIVE_ARCH = YES;
326 | SDKROOT = iphoneos;
327 | TARGETED_DEVICE_FAMILY = "1,2";
328 | };
329 | name = Debug;
330 | };
331 | 088BF8C81F4FAF3C00B5863B /* Release */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | ALWAYS_SEARCH_USER_PATHS = NO;
335 | CLANG_ANALYZER_NONNULL = YES;
336 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
338 | CLANG_CXX_LIBRARY = "libc++";
339 | CLANG_ENABLE_MODULES = YES;
340 | CLANG_ENABLE_OBJC_ARC = YES;
341 | CLANG_WARN_BOOL_CONVERSION = YES;
342 | CLANG_WARN_CONSTANT_CONVERSION = YES;
343 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
344 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
345 | CLANG_WARN_EMPTY_BODY = YES;
346 | CLANG_WARN_ENUM_CONVERSION = YES;
347 | CLANG_WARN_INFINITE_RECURSION = YES;
348 | CLANG_WARN_INT_CONVERSION = YES;
349 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
350 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
351 | CLANG_WARN_UNREACHABLE_CODE = YES;
352 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
353 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
354 | COPY_PHASE_STRIP = NO;
355 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
356 | ENABLE_NS_ASSERTIONS = NO;
357 | ENABLE_STRICT_OBJC_MSGSEND = YES;
358 | GCC_C_LANGUAGE_STANDARD = gnu99;
359 | GCC_NO_COMMON_BLOCKS = YES;
360 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
361 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
362 | GCC_WARN_UNDECLARED_SELECTOR = YES;
363 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
364 | GCC_WARN_UNUSED_FUNCTION = YES;
365 | GCC_WARN_UNUSED_VARIABLE = YES;
366 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
367 | MTL_ENABLE_DEBUG_INFO = NO;
368 | SDKROOT = iphoneos;
369 | TARGETED_DEVICE_FAMILY = "1,2";
370 | VALIDATE_PRODUCT = YES;
371 | };
372 | name = Release;
373 | };
374 | 088BF8CA1F4FAF3C00B5863B /* Debug */ = {
375 | isa = XCBuildConfiguration;
376 | buildSettings = {
377 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
378 | DEVELOPMENT_TEAM = D8MERC5W3E;
379 | INFOPLIST_FILE = JHVerificationCodeView/Info.plist;
380 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
381 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
382 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHVerificationCodeView;
383 | PRODUCT_NAME = "$(TARGET_NAME)";
384 | PROVISIONING_PROFILE = "a6b55bc0-269a-40bc-8d1d-d2de538f4383";
385 | PROVISIONING_PROFILE_SPECIFIER = haocold.develop;
386 | };
387 | name = Debug;
388 | };
389 | 088BF8CB1F4FAF3C00B5863B /* Release */ = {
390 | isa = XCBuildConfiguration;
391 | buildSettings = {
392 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
393 | DEVELOPMENT_TEAM = D8MERC5W3E;
394 | INFOPLIST_FILE = JHVerificationCodeView/Info.plist;
395 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
396 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
397 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHVerificationCodeView;
398 | PRODUCT_NAME = "$(TARGET_NAME)";
399 | PROVISIONING_PROFILE = "a6b55bc0-269a-40bc-8d1d-d2de538f4383";
400 | PROVISIONING_PROFILE_SPECIFIER = haocold.develop;
401 | };
402 | name = Release;
403 | };
404 | 088BF8CD1F4FAF3C00B5863B /* Debug */ = {
405 | isa = XCBuildConfiguration;
406 | buildSettings = {
407 | BUNDLE_LOADER = "$(TEST_HOST)";
408 | INFOPLIST_FILE = JHVerificationCodeViewTests/Info.plist;
409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
410 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHVerificationCodeViewTests;
411 | PRODUCT_NAME = "$(TARGET_NAME)";
412 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JHVerificationCodeView.app/JHVerificationCodeView";
413 | };
414 | name = Debug;
415 | };
416 | 088BF8CE1F4FAF3C00B5863B /* Release */ = {
417 | isa = XCBuildConfiguration;
418 | buildSettings = {
419 | BUNDLE_LOADER = "$(TEST_HOST)";
420 | INFOPLIST_FILE = JHVerificationCodeViewTests/Info.plist;
421 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
422 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHVerificationCodeViewTests;
423 | PRODUCT_NAME = "$(TARGET_NAME)";
424 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JHVerificationCodeView.app/JHVerificationCodeView";
425 | };
426 | name = Release;
427 | };
428 | /* End XCBuildConfiguration section */
429 |
430 | /* Begin XCConfigurationList section */
431 | 088BF8A21F4FAF3C00B5863B /* Build configuration list for PBXProject "JHVerificationCodeView" */ = {
432 | isa = XCConfigurationList;
433 | buildConfigurations = (
434 | 088BF8C71F4FAF3C00B5863B /* Debug */,
435 | 088BF8C81F4FAF3C00B5863B /* Release */,
436 | );
437 | defaultConfigurationIsVisible = 0;
438 | defaultConfigurationName = Release;
439 | };
440 | 088BF8C91F4FAF3C00B5863B /* Build configuration list for PBXNativeTarget "JHVerificationCodeView" */ = {
441 | isa = XCConfigurationList;
442 | buildConfigurations = (
443 | 088BF8CA1F4FAF3C00B5863B /* Debug */,
444 | 088BF8CB1F4FAF3C00B5863B /* Release */,
445 | );
446 | defaultConfigurationIsVisible = 0;
447 | defaultConfigurationName = Release;
448 | };
449 | 088BF8CC1F4FAF3C00B5863B /* Build configuration list for PBXNativeTarget "JHVerificationCodeViewTests" */ = {
450 | isa = XCConfigurationList;
451 | buildConfigurations = (
452 | 088BF8CD1F4FAF3C00B5863B /* Debug */,
453 | 088BF8CE1F4FAF3C00B5863B /* Release */,
454 | );
455 | defaultConfigurationIsVisible = 0;
456 | defaultConfigurationName = Release;
457 | };
458 | /* End XCConfigurationList section */
459 | };
460 | rootObject = 088BF89F1F4FAF3C00B5863B /* Project object */;
461 | }
462 |
--------------------------------------------------------------------------------