Full Code of chernyog/CYPasswordView for AI

master b2df67cc54ca cached
34 files
134.0 KB
37.5k tokens
2 symbols
1 requests
Download .txt
Repository: chernyog/CYPasswordView
Branch: master
Commit: b2df67cc54ca
Files: 34
Total size: 134.0 KB

Directory structure:
gitextract_n2axo8ji/

├── .gitignore
├── CYPasswordView/
│   ├── CYConst.h
│   ├── CYConst.m
│   ├── CYPasswordInputView.h
│   ├── CYPasswordInputView.m
│   ├── CYPasswordView.h
│   ├── CYPasswordView.m
│   ├── NSBundle+CYPasswordView.h
│   ├── NSBundle+CYPasswordView.m
│   ├── UIDevice+Extension.h
│   ├── UIDevice+Extension.m
│   ├── UIView+Extension.h
│   └── UIView+Extension.m
├── CYPasswordView.podspec
├── CYPasswordViewDemo/
│   ├── CYPasswordViewDemo/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── Contents.json
│   │   │   └── arrow.imageset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Info.plist
│   │   ├── MBProgressHUD/
│   │   │   ├── MBProgressHUD+MJ.h
│   │   │   ├── MBProgressHUD+MJ.m
│   │   │   ├── MBProgressHUD.h
│   │   │   └── MBProgressHUD.m
│   │   ├── ViewController.h
│   │   ├── ViewController.m
│   │   └── main.m
│   └── CYPasswordViewDemo.xcodeproj/
│       ├── project.pbxproj
│       └── project.xcworkspace/
│           ├── contents.xcworkspacedata
│           └── xcshareddata/
│               └── IDEWorkspaceChecks.plist
├── LICENSE
└── README.md

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

================================================
FILE: .gitignore
================================================
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate

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


================================================
FILE: CYPasswordView/CYConst.h
================================================
#import <UIKit/UIKit.h>

// 日志输出
#ifdef DEBUG
#define CYLog(...) NSLog(__VA_ARGS__)
#else
#define CYLog(...)
#endif

// RGB颜色
#define CYColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
#define CYColor_A(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)]

// 字体大小
#define CYLabelFont [UIFont boldSystemFontOfSize:13]
#define CYFont(f) [UIFont systemFontOfSize:(f)]
#define CYFontB(f) [UIFont boldSystemFontOfSize:(f)]

// 图片路径
//#define CYPasswordViewSrcName(file) [@"CYPasswordView.bundle" stringByAppendingPathComponent:file]

/** 屏幕的宽高 */
#define CYScreen [UIScreen mainScreen]
#define CYScreenWith CYScreen.bounds.size.width
#define CYScreenHeight CYScreen.bounds.size.height

#define CYNotificationCenter [NSNotificationCenter defaultCenter]

// 常量
/** 密码框的高度 */
UIKIT_EXTERN const CGFloat CYPasswordInputViewHeight;
/** 密码框标题的高度 */
UIKIT_EXTERN const CGFloat CYPasswordViewTitleHeight;
/** 密码框显示或隐藏时间 */
UIKIT_EXTERN const CGFloat CYPasswordViewAnimationDuration;
/** 关闭按钮的宽高 */
UIKIT_EXTERN const CGFloat CYPasswordViewCloseButtonWH;
/** 关闭按钮的左边距 */
UIKIT_EXTERN const CGFloat CYPasswordViewCloseButtonMarginLeft;
/** 输入点的宽高 */
UIKIT_EXTERN const CGFloat CYPasswordViewPointnWH;
/** TextField图片的宽 */
UIKIT_EXTERN const CGFloat CYPasswordViewTextFieldWidth;
/** TextField图片的高 */
UIKIT_EXTERN const CGFloat CYPasswordViewTextFieldHeight;
/** TextField图片向上间距 */
UIKIT_EXTERN const CGFloat CYPasswordViewTextFieldMarginTop;
/** 忘记密码按钮向上间距 */
UIKIT_EXTERN const CGFloat CYPasswordViewForgetPWDButtonMarginTop;

UIKIT_EXTERN NSString *const CYPasswordViewKeyboardNumberKey;

// 通知
UIKIT_EXTERN NSString *const CYPasswordViewCancleButtonClickNotification;
UIKIT_EXTERN NSString *const CYPasswordViewDeleteButtonClickNotification;
UIKIT_EXTERN NSString *const CYPasswordViewNumberButtonClickNotification;
UIKIT_EXTERN NSString *const CYPasswordViewForgetPWDButtonClickNotification;
UIKIT_EXTERN NSString *const CYPasswordViewEnabledUserInteractionNotification;
UIKIT_EXTERN NSString *const CYPasswordViewDisEnabledUserInteractionNotification;


================================================
FILE: CYPasswordView/CYConst.m
================================================

#import "CYConst.h"

// 常量
const CGFloat CYPasswordInputViewHeight = (196 + 216);
const CGFloat CYPasswordViewTitleHeight = 55;
const CGFloat CYPasswordViewAnimationDuration = 0.25;
const CGFloat CYPasswordViewCloseButtonWH = 55;
const CGFloat CYPasswordViewCloseButtonMarginLeft = 0;
const CGFloat CYPasswordViewPointnWH = 10;
const CGFloat CYPasswordViewTextFieldWidth = 297;
const CGFloat CYPasswordViewTextFieldHeight = 50;
const CGFloat CYPasswordViewTextFieldMarginTop = 25;
const CGFloat CYPasswordViewForgetPWDButtonMarginTop = 12;

NSString *const CYPasswordViewKeyboardNumberKey = @"CYPasswordViewKeyboardNumberKey";

// 通知
NSString *const CYPasswordViewCancleButtonClickNotification = @"CYPasswordViewCancleButtonClickNotification";
NSString *const CYPasswordViewDeleteButtonClickNotification = @"CYPasswordViewDeleteButtonClickNotification";
NSString *const CYPasswordViewNumberButtonClickNotification = @"CYPasswordViewNumberButtonClickNotification";
NSString *const CYPasswordViewForgetPWDButtonClickNotification = @"CYPasswordViewForgetPWDButtonClickNotification";
NSString *const CYPasswordViewEnabledUserInteractionNotification = @"CYPasswordViewEnabledUserInteractionNotification";
NSString *const CYPasswordViewDisEnabledUserInteractionNotification = @"CYPasswordViewDisEnabledUserInteractionNotification";


================================================
FILE: CYPasswordView/CYPasswordInputView.h
================================================
//
//  CYPasswordInputView.h
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface CYPasswordInputView : UIView

@property (nonatomic, copy) NSString *title;

@end

================================================
FILE: CYPasswordView/CYPasswordInputView.m
================================================
//
//  CYPasswordInputView.m
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import "CYPasswordInputView.h"
#import "CYConst.h"
#import "UIView+Extension.h"
#import "NSBundle+CYPasswordView.h"

#define kNumCount 6

@interface CYPasswordInputView ()

/** 保存用户输入的数字集合 */
@property (nonatomic, strong) NSMutableArray *inputNumArray;
/** 关闭按钮 */
@property (nonatomic, weak) UIButton *btnClose;
/** 忘记密码 */
@property (nonatomic, weak) UIButton *btnForgetPWD;

@end

@implementation CYPasswordInputView

#pragma mark  - 生命周期方法
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor clearColor];
        /** 注册通知 */
        [self setupNotification];
        /** 添加子控件 */
        [self setupSubViews];
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    // 设置关闭按钮的坐标
    self.btnClose.width = CYPasswordViewCloseButtonWH;
    self.btnClose.height = CYPasswordViewCloseButtonWH;
    self.btnClose.x = CYPasswordViewCloseButtonMarginLeft;
    self.btnClose.centerY = CYPasswordViewTitleHeight * 0.5;

    // 设置忘记密码按钮的坐标
    self.btnForgetPWD.x = CYScreenWith - (CYScreenWith - CYPasswordViewTextFieldWidth) * 0.5 - self.btnForgetPWD.width;
    self.btnForgetPWD.y = CYPasswordViewTitleHeight + CYPasswordViewTextFieldMarginTop + CYPasswordViewTextFieldHeight + CYPasswordViewForgetPWDButtonMarginTop;
}

- (void)dealloc
{
    CYLog(@"cy =========== %@:我走了", [self class]);
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

/** 添加子控件 */
- (void)setupSubViews
{
    /** 关闭按钮 */
    UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeCustom];
    [self addSubview:btnCancel];
    [btnCancel setBackgroundImage:[NSBundle cy_closeImage] forState:UIControlStateNormal];
    [btnCancel setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
    self.btnClose = btnCancel;
    [self.btnClose addTarget:self action:@selector(btnClose_Click:) forControlEvents:UIControlEventTouchUpInside];

    /** 忘记密码按钮 */
    UIButton *btnForgetPWD = [UIButton buttonWithType:UIButtonTypeCustom];
    [self addSubview:btnForgetPWD];
    [btnForgetPWD setTitle:@"忘记密码?" forState:UIControlStateNormal];
    [btnForgetPWD setTitleColor:CYColor(0, 125, 227) forState:UIControlStateNormal];
    btnForgetPWD.titleLabel.font = CYFont(13);
    [btnForgetPWD sizeToFit];
    self.btnForgetPWD = btnForgetPWD;
    [self.btnForgetPWD addTarget:self action:@selector(btnForgetPWD_Click:) forControlEvents:UIControlEventTouchUpInside];
}

/** 注册通知 */
- (void)setupNotification {
    // 用户按下删除键通知
    [CYNotificationCenter addObserver:self selector:@selector(delete) name:CYPasswordViewDeleteButtonClickNotification object:nil];
    // 用户按下数字键通知
    [CYNotificationCenter addObserver:self selector:@selector(number:) name:CYPasswordViewNumberButtonClickNotification object:nil];
    [CYNotificationCenter addObserver:self selector:@selector(disEnalbeCloseButton:) name:CYPasswordViewDisEnabledUserInteractionNotification object:nil];
    [CYNotificationCenter addObserver:self selector:@selector(disEnalbeCloseButton:) name:CYPasswordViewEnabledUserInteractionNotification object:nil];
}

// 按钮点击
- (void)btnClose_Click:(UIButton *)sender {
    [CYNotificationCenter postNotificationName:CYPasswordViewCancleButtonClickNotification object:self];
    [self.inputNumArray removeAllObjects];
}

- (void)btnForgetPWD_Click:(UIButton *)sender {
    [CYNotificationCenter postNotificationName:CYPasswordViewForgetPWDButtonClickNotification object:self];
}

- (void) disEnalbeCloseButton:(NSNotification *)notification{
    BOOL flag = [[notification.object valueForKeyPath:@"enable"] boolValue];
    self.btnClose.userInteractionEnabled = flag;
    self.btnForgetPWD.userInteractionEnabled = flag;
}

- (void)drawRect:(CGRect)rect {
    // 画图
    UIImage *imgBackground = [NSBundle cy_backgroundImage];
    UIImage *imgTextfield = [NSBundle cy_textfieldImage];

    [imgBackground drawInRect:rect];

    CGFloat textfieldY = CYPasswordViewTitleHeight + CYPasswordViewTextFieldMarginTop;
    CGFloat textfieldW = CYPasswordViewTextFieldWidth;
    CGFloat textfieldX = (CYScreenWith - textfieldW) * 0.5;
    CGFloat textfieldH = CYPasswordViewTextFieldHeight;
    [imgTextfield drawInRect:CGRectMake(textfieldX, textfieldY, textfieldW, textfieldH)];

    // 画标题
    NSString *title = self.title ? self.title : @"输入交易密码";

    NSDictionary *arrts = @{NSFontAttributeName:CYFontB(18)};
    CGSize size = [title boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:arrts context:nil].size;
    CGFloat titleW = size.width;
    CGFloat titleH = size.height;
    CGFloat titleX = (self.width - titleW) * 0.5;
    CGFloat titleY = (CYPasswordViewTitleHeight - titleH) * 0.5;
    CGRect titleRect = CGRectMake(titleX, titleY, titleW, titleH);

    NSMutableDictionary *attr = [NSMutableDictionary dictionary];
    attr[NSFontAttributeName] = CYFontB(18);
    attr[NSForegroundColorAttributeName] = CYColor(102, 102, 102);
    [title drawInRect:titleRect withAttributes:attr];

    // 画点
    UIImage *pointImage = [NSBundle cy_pointImage];
    CGFloat pointW = CYPasswordViewPointnWH;
    CGFloat pointH = CYPasswordViewPointnWH;
    CGFloat pointY =  textfieldY + (textfieldH - pointH) * 0.5;
    __block CGFloat pointX;

    // 一个格子的宽度
    CGFloat cellW = textfieldW / kNumCount;
    CGFloat padding = (cellW - pointW) * 0.5;
    [self.inputNumArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        pointX = textfieldX + (2 * idx + 1) * padding + idx * pointW;
        [pointImage drawInRect:CGRectMake(pointX, pointY, pointW, pointH)];
    }];
}

#pragma mark  - 懒加载
- (NSMutableArray *)inputNumArray {
    if (_inputNumArray == nil) {
        _inputNumArray = [NSMutableArray array];
    }
    return _inputNumArray;
}

#pragma mark  - 私有方法
// 响应用户按下删除键事件
- (void)delete {
    [self.inputNumArray removeLastObject];
    [self setNeedsDisplay];
}

// 响应用户按下数字键事件
- (void)number:(NSNotification *)note {
    NSDictionary *userInfo = note.userInfo;
    NSString *numObj = userInfo[CYPasswordViewKeyboardNumberKey];
    if (numObj.length >= kNumCount) return;
    [self.inputNumArray addObject:numObj];
    [self setNeedsDisplay];
}

@end


================================================
FILE: CYPasswordView/CYPasswordView.h
================================================
//
//  CYPasswordView.h
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "CYPasswordInputView.h"
#import "CYConst.h"
#import "NSBundle+CYPasswordView.h"

@interface CYPasswordView : UIView

/** 正在请求时显示的文本 */
@property (nonatomic, copy) NSString *loadingText;

/** 完成的回调block */
@property (nonatomic, copy) void (^finish) (NSString *password);

/** 密码框的标题 */
@property (nonatomic, copy) NSString *title;

/** 弹出密码框 */
- (void)showInView:(UIView *)view;

/** 隐藏键盘 */
- (void)hideKeyboard;

/** 隐藏密码框 */
- (void)hide;

/** 开始加载 */
- (void)startLoading;

/** 加载完成 */
- (void)stopLoading;

/** 请求完成 */
- (void)requestComplete:(BOOL)state;
- (void)requestComplete:(BOOL)state message:(NSString *)message;

@end


================================================
FILE: CYPasswordView/CYPasswordView.m
================================================
//
//  CYPasswordView.m
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import "CYPasswordView.h"
#import "UIView+Extension.h"
#import "UIDevice+Extension.h"

#define kPWDLength 6

@interface CYPasswordView () <UITextFieldDelegate>

/** 输入框 */
@property (nonatomic, strong) CYPasswordInputView *passwordInputView;
@property (nonatomic, strong) UITextField *txfResponsder;

/** 蒙板 */
@property (nonatomic, strong) UIControl *coverView;
/** 返回密码 */
@property (nonatomic, copy) NSString *password;

@property (nonatomic, strong) UIImageView *imgRotation;
@property (nonatomic, strong) UILabel *lblMessage;

@end

@implementation CYPasswordView

#pragma mark  - 常量区
static NSString *tempStr;

#pragma mark  - 生命周期方法
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:CYScreen.bounds];
    if (self) {
        [self setupUI];
    }
    return self;
}

- (void)dealloc
{
    CYLog(@"cy =========== %@:我走了", [self class]);
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setupUI {
    self.backgroundColor = [UIColor clearColor];
    // 蒙版
    [self addSubview:self.coverView];
    // 输入框
    [self addSubview:self.passwordInputView];
    // 响应者
    [self addSubview:self.txfResponsder];
    
    [self.passwordInputView addSubview:self.imgRotation];
    [self.passwordInputView addSubview:self.lblMessage];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.imgRotation.centerX = self.passwordInputView.centerX;
    self.imgRotation.centerY = self.passwordInputView.height * 0.5;
    
    self.lblMessage.centerX = self.passwordInputView.centerX;
    self.lblMessage.centerY = CGRectGetMaxY(self.imgRotation.frame) + CYPasswordViewTextFieldMarginTop;
    self.lblMessage.x = 0;
    self.lblMessage.width = CYScreenWith;
}

#pragma mark  - <UITextFieldDelegate>
#pragma mark  处理字符串 和 删除键
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (!tempStr) {
        tempStr = string;
    } else {
        tempStr = [NSString stringWithFormat:@"%@%@",tempStr,string];
    }
    
    if ([string isEqualToString:@""]) {
        [CYNotificationCenter postNotificationName:CYPasswordViewDeleteButtonClickNotification object:self];
        if (tempStr.length > 0) {   //  删除最后一个字符串
            NSString *lastStr = [tempStr substringToIndex:[tempStr length] - 1];
            tempStr = lastStr;
        }
    } else {
        if (tempStr.length == kPWDLength) {
            if (self.finish) {
                self.finish(tempStr);
                self.finish = nil;
            }
            tempStr = nil;
        }
        NSMutableDictionary *userInfoDict = [NSMutableDictionary dictionary];
        userInfoDict[CYPasswordViewKeyboardNumberKey] = string;
        [CYNotificationCenter postNotificationName:CYPasswordViewNumberButtonClickNotification object:self userInfo:userInfoDict];
    }
    return YES;
}

/** 输入框的取消按钮点击 */
- (void)cancle
{
    [self hideKeyboard:^(BOOL finished) {
        self.inputView.hidden = YES;
        tempStr = nil;
        [self removeFromSuperview];
        [self hideKeyboard:nil];
        [self.inputView setNeedsDisplay];
    }];
}

#pragma mark  - 公开方法
// 关闭键盘
- (void)hideKeyboard
{
    [self hideKeyboard:nil];
}

- (void)hide {
    [self removeFromSuperview];
}

- (void)showInView:(UIView *)view
{
    [view addSubview:self];
    /** 输入框起始frame */
    self.passwordInputView.height = CYPasswordInputViewHeight + UIDevice.safeAreaInsets.bottom * 2;
    self.passwordInputView.y = self.height;
    self.passwordInputView.width = CYScreenWith;
    self.passwordInputView.x = 0;
    /** 弹出键盘 */
    [self showKeyboard];
}

- (void)startLoading {
    [self startRotation:self.imgRotation];
    [CYNotificationCenter postNotificationName:CYPasswordViewDisEnabledUserInteractionNotification object:@{@"enable":@(NO)}];
}

- (void)stopLoading {
    [self stopRotation:self.imgRotation];
    [CYNotificationCenter postNotificationName:CYPasswordViewEnabledUserInteractionNotification object:@{@"enable":@(YES)}];
}

- (void)requestComplete:(BOOL)state {
    if (state) {
        [self requestComplete:state message:@"支付成功"];
    } else {
        [self requestComplete:state message:@"支付失败"];
    }
}
- (void)requestComplete:(BOOL)state message:(NSString *)message {
    if (state) {
        // 请求成功
        self.lblMessage.text = message;
        self.imgRotation.image = [NSBundle cy_successImage];
    } else {
        // 请求失败
        self.lblMessage.text = message;
        self.imgRotation.image = [NSBundle cy_errorImage];
    }
}

#pragma mark  - 私有方法
/** 键盘弹出 */
- (void)showKeyboard {
    [self.txfResponsder becomeFirstResponder];
    [UIView animateWithDuration:CYPasswordViewAnimationDuration delay:0 options:UIViewAnimationOptionTransitionNone animations:^{
        self.passwordInputView.y = (self.height - self.passwordInputView.height);
    } completion:^(BOOL finished) {
        CYLog(@"%@", NSStringFromCGRect(self.passwordInputView.frame));
    }];
}

/** 键盘退下 */
- (void)hideKeyboard:(void (^)(BOOL finished))completion {
    [self.txfResponsder endEditing:NO];
    [UIView animateWithDuration:CYPasswordViewAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        self.inputView.transform = CGAffineTransformIdentity;
    } completion:completion];
}

/**
 *  开始旋转
 */
- (void)startRotation:(UIView *)view {
    _imgRotation.hidden = NO;
    _lblMessage.hidden = NO;
    CABasicAnimation* rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];
    rotationAnimation.duration = 2.0;
    rotationAnimation.cumulative = YES;
    rotationAnimation.repeatCount = MAXFLOAT;
    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

/**
 *  结束旋转
 */
- (void)stopRotation:(UIView *)view {
    //    _imgRotation.hidden = YES;
    //    _lblMessage.hidden = YES;
    [view.layer removeAllAnimations];
}

#pragma mark - Set 方法
- (void)setTitle:(NSString *)title {
    _title = [title copy];
    self.passwordInputView.title = title;
}

- (void)setLoadingText:(NSString *)loadingText {
    _loadingText = [loadingText copy];
    self.lblMessage.text = loadingText;
}

#pragma mark  - 懒加载
- (UIControl *)coverView
{
    if (_coverView == nil)
    {
        _coverView = [[UIControl alloc] init];
        [_coverView setBackgroundColor:[UIColor blackColor]];
        _coverView.alpha = 0.4;
        _coverView.frame = self.bounds;
    }
    return _coverView;
}

- (CYPasswordInputView *)passwordInputView
{
    if (_passwordInputView == nil)
    {
        _passwordInputView = [[CYPasswordInputView alloc] init];
        /** 注册取消按钮点击的通知 */
        [CYNotificationCenter addObserver:self selector:@selector(cancle) name:CYPasswordViewCancleButtonClickNotification object:nil];
    }
    return _passwordInputView;
}

- (UITextField *)txfResponsder
{
    if (_txfResponsder == nil)
    {
        _txfResponsder = [[UITextField alloc] init];
        _txfResponsder.delegate = self;
        _txfResponsder.keyboardType = UIKeyboardTypeNumberPad;
        _txfResponsder.secureTextEntry = YES;
    }
    return _txfResponsder;
}

- (UIImageView *)imgRotation {
    if (_imgRotation == nil) {
        _imgRotation = [[UIImageView alloc] init];
        _imgRotation.image = [NSBundle cy_loadingImage];
        [_imgRotation sizeToFit];
        _imgRotation.hidden = YES;
    }
    return _imgRotation;
}

- (UILabel *)lblMessage {
    if (_lblMessage == nil) {
        _lblMessage = [[UILabel alloc] init];
        _lblMessage.text = @"支付中...";
        _lblMessage.hidden = YES;
        _lblMessage.textColor = [UIColor darkGrayColor];
        _lblMessage.font = CYLabelFont;
        _lblMessage.textAlignment = NSTextAlignmentCenter;
        [_lblMessage sizeToFit];
    }
    return _lblMessage;
}

@end


================================================
FILE: CYPasswordView/NSBundle+CYPasswordView.h
================================================
//
//  NSBundle+NSBundle_CYPasswordView.h
//  CYPasswordViewDemo
//
//  Created by apple on 2017/9/8.
//  Copyright © 2017年 zhssit. All rights reserved.
//  借鉴自:MJRefresh

#import <UIKit/UIKit.h>

@interface NSBundle (NSBundle_CYPasswordView)
+ (instancetype)cy_passwordViewBundle;
+ (UIImage *)cy_closeImage;
+ (UIImage *)cy_backgroundImage;
+ (UIImage *)cy_textfieldImage;
+ (UIImage *)cy_pointImage;
+ (UIImage *)cy_successImage;
+ (UIImage *)cy_errorImage;
+ (UIImage *)cy_loadingImage;

@end


================================================
FILE: CYPasswordView/NSBundle+CYPasswordView.m
================================================
//
//  NSBundle+NSBundle_CYPasswordView.m
//  CYPasswordViewDemo
//
//  Created by apple on 2017/9/8.
//  Copyright © 2017年 zhssit. All rights reserved.
//

#import "NSBundle+CYPasswordView.h"
#import "CYPasswordView.h"

@implementation NSBundle (NSBundle_CYPasswordView)
+ (instancetype)cy_passwordViewBundle
{
    static NSBundle *refreshBundle = nil;
    if (refreshBundle == nil) {
        // 这里不使用mainBundle是为了适配pod 1.x和0.x
        refreshBundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[CYPasswordView class]] pathForResource:@"CYPasswordView" ofType:@"bundle"]];
    }
    return refreshBundle;
}

+ (UIImage *)cy_closeImage {
    static UIImage *_image = nil;
    if (_image == nil) {
        _image = [[UIImage imageWithContentsOfFile:[[self cy_passwordViewBundle] pathForResource:@"password_close@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    return _image;
}
+ (UIImage *)cy_backgroundImage {
    static UIImage *_image = nil;
    if (_image == nil) {
        _image = [[UIImage imageWithContentsOfFile:[[self cy_passwordViewBundle] pathForResource:@"password_background@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    return _image;
}
+ (UIImage *)cy_textfieldImage {
    static UIImage *_image = nil;
    if (_image == nil) {
        _image = [[UIImage imageWithContentsOfFile:[[self cy_passwordViewBundle] pathForResource:@"password_textfield@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    return _image;
}
+ (UIImage *)cy_pointImage {
    static UIImage *_image = nil;
    if (_image == nil) {
        _image = [[UIImage imageWithContentsOfFile:[[self cy_passwordViewBundle] pathForResource:@"password_point@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    return _image;
}
+ (UIImage *)cy_successImage {
    static UIImage *_image = nil;
    if (_image == nil) {
        _image = [[UIImage imageWithContentsOfFile:[[self cy_passwordViewBundle] pathForResource:@"password_success@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    return _image;
}
+ (UIImage *)cy_errorImage {
    static UIImage *_image = nil;
    if (_image == nil) {
        _image = [[UIImage imageWithContentsOfFile:[[self cy_passwordViewBundle] pathForResource:@"password_error@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    return _image;
}
+ (UIImage *)cy_loadingImage {
    static UIImage *_image = nil;
    if (_image == nil) {
        _image = [[UIImage imageWithContentsOfFile:[[self cy_passwordViewBundle] pathForResource:@"password_loading_a@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    return _image;
}

@end


================================================
FILE: CYPasswordView/UIDevice+Extension.h
================================================
//
//  UIDevice+Extension.h
//  CYPasswordViewDemo
//
//  Created by yong.chen on 2020/9/21.
//  Copyright © 2020 zhssit. All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIDevice (Extension)
+ (UIEdgeInsets)safeAreaInsets;
@end

NS_ASSUME_NONNULL_END


================================================
FILE: CYPasswordView/UIDevice+Extension.m
================================================
//
//  UIDevice+Extension.m
//  CYPasswordViewDemo
//
//  Created by yong.chen on 2020/9/21.
//  Copyright © 2020 zhssit. All rights reserved.
//

#import "UIDevice+Extension.h"

@implementation UIDevice (Extension)
+ (UIEdgeInsets)safeAreaInsets {
    if (@available(iOS 11.0, *)) {
        return UIApplication.sharedApplication.keyWindow.safeAreaInsets;
    }
    return UIEdgeInsetsZero;
}


@end


================================================
FILE: CYPasswordView/UIView+Extension.h
================================================
//
//  UIView+Extension.h
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIView (Extension)

// 在分类里面自动生成get,set方法
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat maxX;
@property (nonatomic, assign) CGFloat maxY;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize size;

@end


================================================
FILE: CYPasswordView/UIView+Extension.m
================================================
//
//  UIView+Extension.m
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import "UIView+Extension.h"

@implementation UIView (Extension)

- (void)setX:(CGFloat)x
{
    CGRect frame = self.frame;
    frame.origin.x = x;
    self.frame = frame;
}

- (CGFloat)x
{
    return self.frame.origin.x;
}

- (void)setMaxX:(CGFloat)maxX
{
    self.x = maxX - self.width;
}

- (CGFloat)maxX
{
    return CGRectGetMaxX(self.frame);
}

- (void)setMaxY:(CGFloat)maxY
{
    self.y = maxY - self.height;
}

- (CGFloat)maxY
{
    return CGRectGetMaxY(self.frame);
}

- (void)setY:(CGFloat)y
{
    CGRect frame = self.frame;
    frame.origin.y = y;
    self.frame = frame;
}

- (CGFloat)y
{
    return self.frame.origin.y;
}

- (void)setCenterX:(CGFloat)centerX
{
    CGPoint center = self.center;
    center.x = centerX;
    self.center = center;
}

- (CGFloat)centerX
{
    return self.center.x;
}

- (void)setCenterY:(CGFloat)centerY
{
    CGPoint center = self.center;
    center.y = centerY;
    self.center = center;
}

- (CGFloat)centerY
{
    return self.center.y;
}

- (void)setWidth:(CGFloat)width
{
    CGRect frame = self.frame;
    frame.size.width = width;
    self.frame = frame;
}

- (CGFloat)width
{
    return self.frame.size.width;
}

- (void)setHeight:(CGFloat)height
{
    CGRect frame = self.frame;
    frame.size.height = height;
    self.frame = frame;
}

- (CGFloat)height
{
    return self.frame.size.height;
}

- (void)setSize:(CGSize)size
{
    //    self.width = size.width;
    //    self.height = size.height;
    CGRect frame = self.frame;
    frame.size = size;
    self.frame = frame;
}

- (CGSize)size
{
    return self.frame.size;
}


@end


================================================
FILE: CYPasswordView.podspec
================================================
#
#  Be sure to run `pod spec lint CYPasswordView.podspec' to ensure this is a
#  valid spec and to remove all comments including this before submitting the spec.
#
#  To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
#  To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#

Pod::Spec.new do |s|

  s.name         = "CYPasswordView"
  s.version      = "0.0.4"
  s.authors     = { 'chernyog' => 'chenyios@126.com' }
  s.summary      = "CYPasswordView 是一个模仿支付宝输入支付密码的密码框。"
  s.homepage     = "https://github.com/chernyog/CYPasswordView"
  s.license      =  { :type => "MIT", :file => "LICENSE" }
  s.author             = { "cheny" => "yong.chen@jimubox.com" }
  s.platform     = :ios, "8.0"
  s.source       = { :git => "https://github.com/chernyog/CYPasswordView.git", :tag => "0.0.4" }
  s.source_files  = "CYPasswordView/**/*.{h,m}"
  s.public_header_files = "CYPasswordView/*.h"
  s.resources = "CYPasswordView/CYPasswordView.bundle"
  s.requires_arc = true

end


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/AppDelegate.h
================================================
//
//  AppDelegate.h
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end



================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/AppDelegate.m
================================================
//
//  AppDelegate.m
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. 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.
    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 throttle down OpenGL ES frame rates. 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 inactive 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: CYPasswordViewDemo/CYPasswordViewDemo/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"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/Assets.xcassets/arrow.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "account_next@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/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="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <animations/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </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: CYPasswordViewDemo/CYPasswordViewDemo/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="DDl-6P-qEA">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
    </dependencies>
    <scenes>
        <!--主界面-->
        <scene sceneID="8bQ-cA-W0V">
            <objects>
                <viewController id="IEj-i2-Itd" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="tVX-w8-UKI"/>
                        <viewControllerLayoutGuide type="bottom" id="kxX-sd-cDW"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="kws-Lx-7zZ">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="v06-O8-Rc1" userLabel="button">
                                <rect key="frame" x="40" y="144" width="520" height="50"/>
                                <color key="backgroundColor" red="0.27058823529999998" green="0.63137254899999995" blue="0.99607843139999996" alpha="1" colorSpace="calibratedRGB"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="50" id="zgX-UU-zWl"/>
                                </constraints>
                                <state key="normal" title="购买界面"/>
                                <connections>
                                    <segue destination="BYZ-38-t0r" kind="show" id="hgw-Qo-9Xc"/>
                                </connections>
                            </button>
                        </subviews>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                        <constraints>
                            <constraint firstAttribute="trailingMargin" secondItem="v06-O8-Rc1" secondAttribute="trailing" constant="20" id="73d-E9-jVI"/>
                            <constraint firstItem="v06-O8-Rc1" firstAttribute="leading" secondItem="kws-Lx-7zZ" secondAttribute="leadingMargin" constant="20" id="bn6-2D-YjI"/>
                            <constraint firstItem="v06-O8-Rc1" firstAttribute="top" secondItem="tVX-w8-UKI" secondAttribute="bottom" constant="80" id="fzk-ej-PLS"/>
                        </constraints>
                    </view>
                    <navigationItem key="navigationItem" title="主界面" id="h02-wO-7DD"/>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="vvX-ay-12X" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1052" y="234"/>
        </scene>
        <!--购买-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="onDrag" translatesAutoresizingMaskIntoConstraints="NO" id="7O1-KZ-hfd">
                                <rect key="frame" x="0.0" y="0.0" width="600" height="550"/>
                                <subviews>
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DES-hX-48l" userLabel="容器试图">
                                        <rect key="frame" x="0.0" y="0.0" width="600" height="550"/>
                                        <color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <gestureRecognizers/>
                                    </view>
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OPR-j9-iue" userLabel="商品名称View">
                                        <rect key="frame" x="0.0" y="8" width="600" height="50"/>
                                        <subviews>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="商品名称" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9pa-CN-qh8">
                                                <rect key="frame" x="16" y="16" width="60" height="18"/>
                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                                                <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="XXX宝贝" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ljg-9o-rHc">
                                                <rect key="frame" x="524" y="16" width="59.5" height="18"/>
                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                                                <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                <color key="textColor" red="0.1333333333" green="0.1333333333" blue="0.1333333333" alpha="1" colorSpace="calibratedRGB"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="J4b-o0-qGx" userLabel="水平分割线">
                                                <rect key="frame" x="16" y="49" width="584" height="1"/>
                                                <color key="backgroundColor" red="0.86666666670000003" green="0.86666666670000003" blue="0.86666666670000003" alpha="1" colorSpace="calibratedRGB"/>
                                                <constraints>
                                                    <constraint firstAttribute="height" constant="1" id="EKF-mC-cEo"/>
                                                </constraints>
                                            </view>
                                        </subviews>
                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                        <constraints>
                                            <constraint firstItem="J4b-o0-qGx" firstAttribute="leading" secondItem="9pa-CN-qh8" secondAttribute="leading" id="6I6-tx-9Wn"/>
                                            <constraint firstAttribute="trailing" secondItem="J4b-o0-qGx" secondAttribute="trailing" id="BUH-h9-0FG"/>
                                            <constraint firstItem="9pa-CN-qh8" firstAttribute="leading" secondItem="OPR-j9-iue" secondAttribute="leading" constant="16" id="St0-a0-1J1"/>
                                            <constraint firstAttribute="bottom" secondItem="J4b-o0-qGx" secondAttribute="bottom" id="UTA-aW-aSr"/>
                                            <constraint firstItem="9pa-CN-qh8" firstAttribute="centerY" secondItem="OPR-j9-iue" secondAttribute="centerY" id="aMZ-qr-V08"/>
                                            <constraint firstAttribute="height" constant="50" id="jUl-9k-sMd"/>
                                            <constraint firstItem="Ljg-9o-rHc" firstAttribute="centerY" secondItem="OPR-j9-iue" secondAttribute="centerY" id="mDz-OZ-Hbi"/>
                                            <constraint firstAttribute="trailing" secondItem="Ljg-9o-rHc" secondAttribute="trailing" constant="16" id="qVe-nH-5GQ"/>
                                        </constraints>
                                    </view>
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bmU-KF-Qdl" userLabel="商品金额View">
                                        <rect key="frame" x="0.0" y="58" width="600" height="50"/>
                                        <subviews>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="商品金额" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SRL-8S-HCB">
                                                <rect key="frame" x="16" y="16" width="60" height="18"/>
                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                                                <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="10000元" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NIx-gE-MHL">
                                                <rect key="frame" x="525.5" y="16" width="58.5" height="18"/>
                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                                                <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                <color key="textColor" red="0.1333333333" green="0.1333333333" blue="0.1333333333" alpha="1" colorSpace="calibratedRGB"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8It-iH-axa" userLabel="水平分割线">
                                                <rect key="frame" x="16" y="49" width="584" height="1"/>
                                                <color key="backgroundColor" red="0.86666666670000003" green="0.86666666670000003" blue="0.86666666670000003" alpha="1" colorSpace="calibratedRGB"/>
                                            </view>
                                        </subviews>
                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                        <constraints>
                                            <constraint firstItem="SRL-8S-HCB" firstAttribute="centerY" secondItem="bmU-KF-Qdl" secondAttribute="centerY" id="Ue4-9r-hw8"/>
                                            <constraint firstAttribute="bottom" secondItem="8It-iH-axa" secondAttribute="bottom" id="dV6-vs-cMm"/>
                                            <constraint firstItem="NIx-gE-MHL" firstAttribute="centerY" secondItem="bmU-KF-Qdl" secondAttribute="centerY" id="wgc-Aa-IER"/>
                                        </constraints>
                                    </view>
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OMc-Hc-5E7" userLabel="选择银行卡View">
                                        <rect key="frame" x="0.0" y="108" width="600" height="50"/>
                                        <subviews>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="选择银行卡" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ln4-Lw-Vue">
                                                <rect key="frame" x="16" y="16" width="75" height="18"/>
                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                                                <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="招商银行(8888)" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cmj-2Q-Mph">
                                                <rect key="frame" x="460" y="16" width="107" height="18"/>
                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                                                <fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
                                                <color key="textColor" red="0.1333333333" green="0.1333333333" blue="0.1333333333" alpha="1" colorSpace="calibratedRGB"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                            <button opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UXP-E8-67d" userLabel="向右箭头">
                                                <rect key="frame" x="576" y="18" width="8" height="13"/>
                                                <state key="normal" backgroundImage="arrow">
                                                    <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
                                                </state>
                                            </button>
                                        </subviews>
                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                        <gestureRecognizers/>
                                        <constraints>
                                            <constraint firstItem="UXP-E8-67d" firstAttribute="centerY" secondItem="OMc-Hc-5E7" secondAttribute="centerY" id="0fu-6U-2aW"/>
                                            <constraint firstItem="UXP-E8-67d" firstAttribute="leading" secondItem="cmj-2Q-Mph" secondAttribute="trailing" constant="9" id="2Nm-8r-eN2"/>
                                            <constraint firstItem="cmj-2Q-Mph" firstAttribute="centerY" secondItem="UXP-E8-67d" secondAttribute="centerY" id="k5G-mx-Wpt"/>
                                            <constraint firstItem="Ln4-Lw-Vue" firstAttribute="centerY" secondItem="OMc-Hc-5E7" secondAttribute="centerY" id="vDn-uc-NZh"/>
                                        </constraints>
                                    </view>
                                </subviews>
                                <color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstItem="UXP-E8-67d" firstAttribute="trailing" secondItem="NIx-gE-MHL" secondAttribute="trailing" id="0y6-aq-XIJ"/>
                                    <constraint firstItem="Ln4-Lw-Vue" firstAttribute="leading" secondItem="SRL-8S-HCB" secondAttribute="leading" id="75j-6R-mvm"/>
                                    <constraint firstItem="bmU-KF-Qdl" firstAttribute="height" secondItem="OPR-j9-iue" secondAttribute="height" id="8O1-hA-UOd"/>
                                    <constraint firstAttribute="trailing" secondItem="OPR-j9-iue" secondAttribute="trailing" id="COa-SN-ilE"/>
                                    <constraint firstItem="OMc-Hc-5E7" firstAttribute="top" secondItem="bmU-KF-Qdl" secondAttribute="bottom" id="Edg-8D-4AO"/>
                                    <constraint firstAttribute="bottom" secondItem="DES-hX-48l" secondAttribute="bottom" id="Foi-p8-kma"/>
                                    <constraint firstItem="DES-hX-48l" firstAttribute="centerX" secondItem="7O1-KZ-hfd" secondAttribute="centerX" id="Fqq-g1-WNw"/>
                                    <constraint firstItem="OPR-j9-iue" firstAttribute="top" secondItem="7O1-KZ-hfd" secondAttribute="top" constant="8" id="H2R-Gc-gk8"/>
                                    <constraint firstItem="bmU-KF-Qdl" firstAttribute="top" secondItem="OPR-j9-iue" secondAttribute="bottom" id="Kav-RO-zuw"/>
                                    <constraint firstItem="bmU-KF-Qdl" firstAttribute="leading" secondItem="OPR-j9-iue" secondAttribute="leading" id="Ls5-wu-rZq"/>
                                    <constraint firstItem="SRL-8S-HCB" firstAttribute="leading" secondItem="9pa-CN-qh8" secondAttribute="leading" id="SkB-E9-TaN"/>
                                    <constraint firstItem="DES-hX-48l" firstAttribute="top" secondItem="7O1-KZ-hfd" secondAttribute="top" id="WQM-gi-kdn"/>
                                    <constraint firstAttribute="trailing" secondItem="DES-hX-48l" secondAttribute="trailing" id="XSr-oF-Tzf"/>
                                    <constraint firstItem="OMc-Hc-5E7" firstAttribute="trailing" secondItem="bmU-KF-Qdl" secondAttribute="trailing" id="ZEs-y9-vbm"/>
                                    <constraint firstItem="OMc-Hc-5E7" firstAttribute="height" secondItem="bmU-KF-Qdl" secondAttribute="height" id="ZoV-sS-aOX"/>
                                    <constraint firstItem="DES-hX-48l" firstAttribute="centerY" secondItem="7O1-KZ-hfd" secondAttribute="centerY" id="aM4-AA-q65"/>
                                    <constraint firstItem="DES-hX-48l" firstAttribute="leading" secondItem="7O1-KZ-hfd" secondAttribute="leading" id="cx9-Ft-VRp"/>
                                    <constraint firstItem="8It-iH-axa" firstAttribute="height" secondItem="J4b-o0-qGx" secondAttribute="height" id="cyR-yG-pKM"/>
                                    <constraint firstItem="OPR-j9-iue" firstAttribute="leading" secondItem="7O1-KZ-hfd" secondAttribute="leading" id="dNB-ew-jFD"/>
                                    <constraint firstItem="8It-iH-axa" firstAttribute="trailing" secondItem="J4b-o0-qGx" secondAttribute="trailing" id="f5T-QO-FyM"/>
                                    <constraint firstItem="bmU-KF-Qdl" firstAttribute="trailing" secondItem="OPR-j9-iue" secondAttribute="trailing" id="m7e-5q-JUN"/>
                                    <constraint firstItem="8It-iH-axa" firstAttribute="leading" secondItem="J4b-o0-qGx" secondAttribute="leading" id="oLa-ef-mCC"/>
                                    <constraint firstItem="OMc-Hc-5E7" firstAttribute="leading" secondItem="bmU-KF-Qdl" secondAttribute="leading" id="oVQ-Kf-izK"/>
                                    <constraint firstItem="NIx-gE-MHL" firstAttribute="trailing" secondItem="Ljg-9o-rHc" secondAttribute="trailing" id="pAG-WL-7sM"/>
                                </constraints>
                            </scrollView>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QkU-Ph-Kte">
                                <rect key="frame" x="0.0" y="550" width="600" height="50"/>
                                <color key="backgroundColor" red="0.27058823529411763" green="0.63137254901960782" blue="0.99607843137254903" alpha="1" colorSpace="calibratedRGB"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="50" id="QLZ-lg-ksQ"/>
                                </constraints>
                                <fontDescription key="fontDescription" type="system" weight="light" pointSize="18"/>
                                <state key="normal" title="确认购买">
                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
                                </state>
                                <connections>
                                    <action selector="showPasswordView:" destination="BYZ-38-t0r" eventType="touchUpInside" id="UAX-cH-Xhn"/>
                                </connections>
                            </button>
                        </subviews>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                        <constraints>
                            <constraint firstItem="QkU-Ph-Kte" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailing" id="2gT-KJ-fEp"/>
                            <constraint firstItem="7O1-KZ-hfd" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="cte-5m-J0j"/>
                            <constraint firstItem="7O1-KZ-hfd" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="fe0-jJ-hL8"/>
                            <constraint firstAttribute="trailing" secondItem="7O1-KZ-hfd" secondAttribute="trailing" id="gpo-W4-ub7"/>
                            <constraint firstAttribute="bottomMargin" secondItem="QkU-Ph-Kte" secondAttribute="bottom" id="oPf-jW-ceV"/>
                            <constraint firstItem="QkU-Ph-Kte" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="y2P-bR-VgB"/>
                            <constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="7O1-KZ-hfd" secondAttribute="bottom" constant="50" id="zUo-EF-wAt"/>
                        </constraints>
                    </view>
                    <navigationItem key="navigationItem" title="购买" id="6H4-tc-def"/>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1747" y="234"/>
        </scene>
        <!--Navigation Controller-->
        <scene sceneID="QD5-j8-cSO">
            <objects>
                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="DDl-6P-qEA" sceneMemberID="viewController">
                    <toolbarItems/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="fkk-EW-3Jb">
                        <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <nil name="viewControllers"/>
                    <connections>
                        <segue destination="IEj-i2-Itd" kind="relationship" relationship="rootViewController" id="s0e-uY-kad"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="SMU-gO-kOA" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="379" y="234"/>
        </scene>
    </scenes>
    <resources>
        <image name="arrow" width="8" height="13"/>
    </resources>
</document>


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/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>en</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>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<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>
</dict>
</plist>


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD+MJ.h
================================================
//
//  MBProgressHUD+MJ.h
//
//  Created by MJ Lee on 13/4/18.
//  Copyright (c) 2015年 itcast. All rights reserved.
//


#import "MBProgressHUD.h"

@interface MBProgressHUD (MJ)
+ (void)showSuccess:(NSString *)success toView:(UIView *)view;
+ (void)showError:(NSString *)error toView:(UIView *)view;

+ (MBProgressHUD *)showMessage:(NSString *)message toView:(UIView *)view;


+ (void)showSuccess:(NSString *)success;
+ (void)showError:(NSString *)error;

+ (MBProgressHUD *)showMessage:(NSString *)message;

+ (void)hideHUDForView:(UIView *)view;
+ (void)hideHUD;

@end


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD+MJ.m
================================================
//
//  MBProgressHUD+MJ.m
//
//  Created by MJ Lee on 13/4/18.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "MBProgressHUD+MJ.h"

@implementation MBProgressHUD (MJ)
#pragma mark 显示信息
+ (void)show:(NSString *)text icon:(NSString *)icon view:(UIView *)view
{
//    if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
    //在StatusBarHud 显示期间,由于lastObject的Frame的缘故将导致
    if (view == nil) view = [[UIApplication sharedApplication] keyWindow];
    // 快速显示一个提示信息
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
    hud.labelText = text;
    // 设置图片
    hud.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"MBProgressHUD.bundle/%@", icon]]];
    // 再设置模式
    hud.mode = MBProgressHUDModeCustomView;
    
    // 隐藏时候从父控件中移除
    hud.removeFromSuperViewOnHide = YES;
    
    // 1秒之后再消失
    [hud hide:YES afterDelay:0.7];
}

#pragma mark 显示错误信息
+ (void)showError:(NSString *)error toView:(UIView *)view{
    [self show:error icon:@"error.png" view:view];
}

+ (void)showSuccess:(NSString *)success toView:(UIView *)view
{
    [self show:success icon:@"success.png" view:view];
}

#pragma mark 显示一些信息
+ (MBProgressHUD *)showMessage:(NSString *)message toView:(UIView *)view {
//    if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
    //在StatusBarHud 显示期间,由于lastObject的Frame的缘故将导致
    if (view == nil) view = [[UIApplication sharedApplication] keyWindow];

    // 快速显示一个提示信息
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
    hud.labelText = message;
    // 隐藏时候从父控件中移除
    hud.removeFromSuperViewOnHide = YES;
    // YES代表需要蒙版效果
    hud.dimBackground = YES;
    return hud;
}

+ (void)showSuccess:(NSString *)success
{
    [self showSuccess:success toView:nil];
}

+ (void)showError:(NSString *)error
{
    [self showError:error toView:nil];
}

+ (MBProgressHUD *)showMessage:(NSString *)message
{
    return [self showMessage:message toView:nil];
}

+ (void)hideHUDForView:(UIView *)view
{
//    if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
    //在StatusBarHud 显示期间,由于lastObject的Frame的缘故将导致
    if (view == nil) view = [[UIApplication sharedApplication] keyWindow];
    [self hideHUDForView:view animated:YES];
}

+ (void)hideHUD
{
    [self hideHUDForView:nil];
}
@end


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD.h
================================================
//
//  MBProgressHUD.h
//  Version 0.9
//  Created by Matej Bukovinski on 2.4.09.
//

// This code is distributed under the terms and conditions of the MIT license. 

// Copyright (c) 2013 Matej Bukovinski
//
// 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.

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>

@protocol MBProgressHUDDelegate;


typedef enum {
	/** Progress is shown using an UIActivityIndicatorView. This is the default. */
	MBProgressHUDModeIndeterminate,
	/** Progress is shown using a round, pie-chart like, progress view. */
	MBProgressHUDModeDeterminate,
	/** Progress is shown using a horizontal progress bar */
	MBProgressHUDModeDeterminateHorizontalBar,
	/** Progress is shown using a ring-shaped progress view. */
	MBProgressHUDModeAnnularDeterminate,
	/** Shows a custom view */
	MBProgressHUDModeCustomView,
	/** Shows only labels */
	MBProgressHUDModeText
} MBProgressHUDMode;

typedef enum {
	/** Opacity animation */
	MBProgressHUDAnimationFade,
	/** Opacity + scale animation */
	MBProgressHUDAnimationZoom,
	MBProgressHUDAnimationZoomOut = MBProgressHUDAnimationZoom,
	MBProgressHUDAnimationZoomIn
} MBProgressHUDAnimation;


#ifndef MB_INSTANCETYPE
#if __has_feature(objc_instancetype)
	#define MB_INSTANCETYPE instancetype
#else
	#define MB_INSTANCETYPE id
#endif
#endif

#ifndef MB_STRONG
#if __has_feature(objc_arc)
	#define MB_STRONG strong
#else
	#define MB_STRONG retain
#endif
#endif

#ifndef MB_WEAK
#if __has_feature(objc_arc_weak)
	#define MB_WEAK weak
#elif __has_feature(objc_arc)
	#define MB_WEAK unsafe_unretained
#else
	#define MB_WEAK assign
#endif
#endif

#if NS_BLOCKS_AVAILABLE
typedef void (^MBProgressHUDCompletionBlock)();
#endif


/** 
 * Displays a simple HUD window containing a progress indicator and two optional labels for short messages.
 *
 * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class.
 * The MBProgressHUD window spans over the entire space given to it by the initWithFrame constructor and catches all
 * user input on this region, thereby preventing the user operations on components below the view. The HUD itself is
 * drawn centered as a rounded semi-transparent view which resizes depending on the user specified content.
 *
 * This view supports four modes of operation:
 * - MBProgressHUDModeIndeterminate - shows a UIActivityIndicatorView
 * - MBProgressHUDModeDeterminate - shows a custom round progress indicator
 * - MBProgressHUDModeAnnularDeterminate - shows a custom annular progress indicator
 * - MBProgressHUDModeCustomView - shows an arbitrary, user specified view (@see customView)
 *
 * All three modes can have optional labels assigned:
 * - If the labelText property is set and non-empty then a label containing the provided content is placed below the
 *   indicator view.
 * - If also the detailsLabelText property is set then another label is placed below the first label.
 */
@interface MBProgressHUD : UIView

/**
 * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:.
 * 
 * @param view The view that the HUD will be added to
 * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use
 * animations while appearing.
 * @return A reference to the created HUD.
 *
 * @see hideHUDForView:animated:
 * @see animationType
 */
+ (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated;

/**
 * Finds the top-most HUD subview and hides it. The counterpart to this method is showHUDAddedTo:animated:.
 *
 * @param view The view that is going to be searched for a HUD subview.
 * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use
 * animations while disappearing.
 * @return YES if a HUD was found and removed, NO otherwise. 
 *
 * @see showHUDAddedTo:animated:
 * @see animationType
 */
+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated;

/**
 * Finds all the HUD subviews and hides them. 
 *
 * @param view The view that is going to be searched for HUD subviews.
 * @param animated If set to YES the HUDs will disappear using the current animationType. If set to NO the HUDs will not use
 * animations while disappearing.
 * @return the number of HUDs found and removed.
 *
 * @see hideHUDForView:animated:
 * @see animationType
 */
+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated;

/**
 * Finds the top-most HUD subview and returns it. 
 *
 * @param view The view that is going to be searched.
 * @return A reference to the last HUD subview discovered.
 */
+ (MB_INSTANCETYPE)HUDForView:(UIView *)view;

/**
 * Finds all HUD subviews and returns them.
 *
 * @param view The view that is going to be searched.
 * @return All found HUD views (array of MBProgressHUD objects).
 */
+ (NSArray *)allHUDsForView:(UIView *)view;

/**
 * A convenience constructor that initializes the HUD with the window's bounds. Calls the designated constructor with
 * window.bounds as the parameter.
 *
 * @param window The window instance that will provide the bounds for the HUD. Should be the same instance as
 * the HUD's superview (i.e., the window that the HUD will be added to).
 */
- (id)initWithWindow:(UIWindow *)window;

/**
 * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with
 * view.bounds as the parameter
 *
 * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as
 * the HUD's superview (i.e., the view that the HUD will be added to).
 */
- (id)initWithView:(UIView *)view;

/** 
 * Display the HUD. You need to make sure that the main thread completes its run loop soon after this method call so
 * the user interface can be updated. Call this method when your task is already set-up to be executed in a new thread
 * (e.g., when using something like NSOperation or calling an asynchronous call like NSURLRequest).
 *
 * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use
 * animations while appearing.
 *
 * @see animationType
 */
- (void)show:(BOOL)animated;

/** 
 * Hide the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to
 * hide the HUD when your task completes.
 *
 * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use
 * animations while disappearing.
 *
 * @see animationType
 */
- (void)hide:(BOOL)animated;

/** 
 * Hide the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to
 * hide the HUD when your task completes.
 *
 * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use
 * animations while disappearing.
 * @param delay Delay in seconds until the HUD is hidden.
 *
 * @see animationType
 */
- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay;

/** 
 * Shows the HUD while a background task is executing in a new thread, then hides the HUD.
 *
 * This method also takes care of autorelease pools so your method does not have to be concerned with setting up a
 * pool.
 *
 * @param method The method to be executed while the HUD is shown. This method will be executed in a new thread.
 * @param target The object that the target method belongs to.
 * @param object An optional object to be passed to the method.
 * @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will not use
 * animations while (dis)appearing.
 */
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated;

#if NS_BLOCKS_AVAILABLE

/**
 * Shows the HUD while a block is executing on a background queue, then hides the HUD.
 *
 * @see showAnimated:whileExecutingBlock:onQueue:completionBlock:
 */
- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block;

/**
 * Shows the HUD while a block is executing on a background queue, then hides the HUD.
 *
 * @see showAnimated:whileExecutingBlock:onQueue:completionBlock:
 */
- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(MBProgressHUDCompletionBlock)completion;

/**
 * Shows the HUD while a block is executing on the specified dispatch queue, then hides the HUD.
 *
 * @see showAnimated:whileExecutingBlock:onQueue:completionBlock:
 */
- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue;

/** 
 * Shows the HUD while a block is executing on the specified dispatch queue, executes completion block on the main queue, and then hides the HUD.
 *
 * @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will
 * not use animations while (dis)appearing.
 * @param block The block to be executed while the HUD is shown.
 * @param queue The dispatch queue on which the block should be executed.
 * @param completion The block to be executed on completion.
 *
 * @see completionBlock
 */
- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue
		  completionBlock:(MBProgressHUDCompletionBlock)completion;

/**
 * A block that gets called after the HUD was completely hidden.
 */
@property (copy) MBProgressHUDCompletionBlock completionBlock;

#endif

/** 
 * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate.
 *
 * @see MBProgressHUDMode
 */
@property (assign) MBProgressHUDMode mode;

/**
 * The animation type that should be used when the HUD is shown and hidden. 
 *
 * @see MBProgressHUDAnimation
 */
@property (assign) MBProgressHUDAnimation animationType;

/**
 * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView.
 * For best results use a 37 by 37 pixel view (so the bounds match the built in indicator bounds). 
 */
@property (MB_STRONG) UIView *customView;

/** 
 * The HUD delegate object. 
 *
 * @see MBProgressHUDDelegate
 */
@property (MB_WEAK) id<MBProgressHUDDelegate> delegate;

/** 
 * An optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit
 * the entire text. If the text is too long it will get clipped by displaying "..." at the end. If left unchanged or
 * set to @"", then no message is displayed.
 */
@property (copy) NSString *labelText;

/** 
 * An optional details message displayed below the labelText message. This message is displayed only if the labelText
 * property is also set and is different from an empty string (@""). The details text can span multiple lines. 
 */
@property (copy) NSString *detailsLabelText;

/** 
 * The opacity of the HUD window. Defaults to 0.8 (80% opacity). 
 */
@property (assign) float opacity;

/**
 * The color of the HUD window. Defaults to black. If this property is set, color is set using
 * this UIColor and the opacity property is not used.  using retain because performing copy on
 * UIColor base colors (like [UIColor greenColor]) cause problems with the copyZone.
 */
@property (MB_STRONG) UIColor *color;

/** 
 * The x-axis offset of the HUD relative to the centre of the superview. 
 */
@property (assign) float xOffset;

/** 
 * The y-axis offset of the HUD relative to the centre of the superview. 
 */
@property (assign) float yOffset;

/**
 * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). 
 * Defaults to 20.0
 */
@property (assign) float margin;

/**
 * The corner radius for the HUD
 * Defaults to 10.0
 */
@property (assign) float cornerRadius;

/** 
 * Cover the HUD background view with a radial gradient. 
 */
@property (assign) BOOL dimBackground;

/*
 * Grace period is the time (in seconds) that the invoked method may be run without 
 * showing the HUD. If the task finishes before the grace time runs out, the HUD will
 * not be shown at all. 
 * This may be used to prevent HUD display for very short tasks.
 * Defaults to 0 (no grace time).
 * Grace time functionality is only supported when the task status is known!
 * @see taskInProgress
 */
@property (assign) float graceTime;

/**
 * The minimum time (in seconds) that the HUD is shown. 
 * This avoids the problem of the HUD being shown and than instantly hidden.
 * Defaults to 0 (no minimum show time).
 */
@property (assign) float minShowTime;

/**
 * Indicates that the executed operation is in progress. Needed for correct graceTime operation.
 * If you don't set a graceTime (different than 0.0) this does nothing.
 * This property is automatically set when using showWhileExecuting:onTarget:withObject:animated:.
 * When threading is done outside of the HUD (i.e., when the show: and hide: methods are used directly),
 * you need to set this property when your task starts and completes in order to have normal graceTime 
 * functionality.
 */
@property (assign) BOOL taskInProgress;

/**
 * Removes the HUD from its parent view when hidden. 
 * Defaults to NO. 
 */
@property (assign) BOOL removeFromSuperViewOnHide;

/** 
 * Font to be used for the main label. Set this property if the default is not adequate. 
 */
@property (MB_STRONG) UIFont* labelFont;

/**
 * Color to be used for the main label. Set this property if the default is not adequate.
 */
@property (MB_STRONG) UIColor* labelColor;

/**
 * Font to be used for the details label. Set this property if the default is not adequate.
 */
@property (MB_STRONG) UIFont* detailsLabelFont;

/** 
 * Color to be used for the details label. Set this property if the default is not adequate.
 */
@property (MB_STRONG) UIColor* detailsLabelColor;

/**
 * The color of the activity indicator. Defaults to [UIColor whiteColor]
 * Does nothing on pre iOS 5.
 */
@property (MB_STRONG) UIColor *activityIndicatorColor;

/** 
 * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. 
 */
@property (assign) float progress;

/**
 * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size).
 */
@property (assign) CGSize minSize;


/**
 * The actual size of the HUD bezel.
 * You can use this to limit touch handling on the bezel aria only.
 * @see https://github.com/jdg/MBProgressHUD/pull/200
 */
@property (atomic, assign, readonly) CGSize size;


/**
 * Force the HUD dimensions to be equal if possible. 
 */
@property (assign, getter = isSquare) BOOL square;

@end


@protocol MBProgressHUDDelegate <NSObject>

@optional

/** 
 * Called after the HUD was fully hidden from the screen. 
 */
- (void)hudWasHidden:(MBProgressHUD *)hud;

@end


/**
 * A progress view for showing definite progress by filling up a circle (pie chart).
 */
@interface MBRoundProgressView : UIView 

/**
 * Progress (0.0 to 1.0)
 */
@property (nonatomic, assign) float progress;

/**
 * Indicator progress color.
 * Defaults to white [UIColor whiteColor]
 */
@property (nonatomic, MB_STRONG) UIColor *progressTintColor;

/**
 * Indicator background (non-progress) color.
 * Defaults to translucent white (alpha 0.1)
 */
@property (nonatomic, MB_STRONG) UIColor *backgroundTintColor;

/*
 * Display mode - NO = round or YES = annular. Defaults to round.
 */
@property (nonatomic, assign, getter = isAnnular) BOOL annular;

@end


/**
 * A flat bar progress view. 
 */
@interface MBBarProgressView : UIView

/**
 * Progress (0.0 to 1.0)
 */
@property (nonatomic, assign) float progress;

/**
 * Bar border line color.
 * Defaults to white [UIColor whiteColor].
 */
@property (nonatomic, MB_STRONG) UIColor *lineColor;

/**
 * Bar background color.
 * Defaults to clear [UIColor clearColor];
 */
@property (nonatomic, MB_STRONG) UIColor *progressRemainingColor;

/**
 * Bar progress color.
 * Defaults to white [UIColor whiteColor].
 */
@property (nonatomic, MB_STRONG) UIColor *progressColor;

@end


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD.m
================================================
//
// MBProgressHUD.m
// Version 0.9
// Created by Matej Bukovinski on 2.4.09.
//

#import "MBProgressHUD.h"
#import <tgmath.h>


#if __has_feature(objc_arc)
	#define MB_AUTORELEASE(exp) exp
	#define MB_RELEASE(exp) exp
	#define MB_RETAIN(exp) exp
#else
	#define MB_AUTORELEASE(exp) [exp autorelease]
	#define MB_RELEASE(exp) [exp release]
	#define MB_RETAIN(exp) [exp retain]
#endif

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
    #define MBLabelAlignmentCenter NSTextAlignmentCenter
#else
    #define MBLabelAlignmentCenter UITextAlignmentCenter
#endif

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
	#define MB_TEXTSIZE(text, font) [text length] > 0 ? [text \
		sizeWithAttributes:@{NSFontAttributeName:font}] : CGSizeZero;
#else
	#define MB_TEXTSIZE(text, font) [text length] > 0 ? [text sizeWithFont:font] : CGSizeZero;
#endif

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
	#define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \
		boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin) \
		attributes:@{NSFontAttributeName:font} context:nil].size : CGSizeZero;
#else
	#define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \
		sizeWithFont:font constrainedToSize:maxSize lineBreakMode:mode] : CGSizeZero;
#endif

#ifndef kCFCoreFoundationVersionNumber_iOS_7_0
	#define kCFCoreFoundationVersionNumber_iOS_7_0 847.20
#endif

#ifndef kCFCoreFoundationVersionNumber_iOS_8_0
	#define kCFCoreFoundationVersionNumber_iOS_8_0 1129.15
#endif


static const CGFloat kPadding = 4.f;
static const CGFloat kLabelFontSize = 16.f;
static const CGFloat kDetailsLabelFontSize = 12.f;


@interface MBProgressHUD () {
	BOOL useAnimation;
	SEL methodForExecution;
	id targetForExecution;
	id objectForExecution;
	UILabel *label;
	UILabel *detailsLabel;
	BOOL isFinished;
	CGAffineTransform rotationTransform;
}

@property (atomic, MB_STRONG) UIView *indicator;
@property (atomic, MB_STRONG) NSTimer *graceTimer;
@property (atomic, MB_STRONG) NSTimer *minShowTimer;
@property (atomic, MB_STRONG) NSDate *showStarted;


@end


@implementation MBProgressHUD

#pragma mark - Properties

@synthesize animationType;
@synthesize delegate;
@synthesize opacity;
@synthesize color;
@synthesize labelFont;
@synthesize labelColor;
@synthesize detailsLabelFont;
@synthesize detailsLabelColor;
@synthesize indicator;
@synthesize xOffset;
@synthesize yOffset;
@synthesize minSize;
@synthesize square;
@synthesize margin;
@synthesize dimBackground;
@synthesize graceTime;
@synthesize minShowTime;
@synthesize graceTimer;
@synthesize minShowTimer;
@synthesize taskInProgress;
@synthesize removeFromSuperViewOnHide;
@synthesize customView;
@synthesize showStarted;
@synthesize mode;
@synthesize labelText;
@synthesize detailsLabelText;
@synthesize progress;
@synthesize size;
@synthesize activityIndicatorColor;
#if NS_BLOCKS_AVAILABLE
@synthesize completionBlock;
#endif

#pragma mark - Class methods

+ (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated {
	MBProgressHUD *hud = [[self alloc] initWithView:view];
	[view addSubview:hud];
	[hud show:animated];
	return MB_AUTORELEASE(hud);
}

+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated {
	MBProgressHUD *hud = [self HUDForView:view];
	if (hud != nil) {
		hud.removeFromSuperViewOnHide = YES;
		[hud hide:animated];
		return YES;
	}
	return NO;
}

+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated {
	NSArray *huds = [MBProgressHUD allHUDsForView:view];
	for (MBProgressHUD *hud in huds) {
		hud.removeFromSuperViewOnHide = YES;
		[hud hide:animated];
	}
	return [huds count];
}

+ (MB_INSTANCETYPE)HUDForView:(UIView *)view {
	NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator];
	for (UIView *subview in subviewsEnum) {
		if ([subview isKindOfClass:self]) {
			return (MBProgressHUD *)subview;
		}
	}
	return nil;
}

+ (NSArray *)allHUDsForView:(UIView *)view {
	NSMutableArray *huds = [NSMutableArray array];
	NSArray *subviews = view.subviews;
	for (UIView *aView in subviews) {
		if ([aView isKindOfClass:self]) {
			[huds addObject:aView];
		}
	}
	return [NSArray arrayWithArray:huds];
}

#pragma mark - Lifecycle

- (id)initWithFrame:(CGRect)frame {
	self = [super initWithFrame:frame];
	if (self) {
		// Set default values for properties
		self.animationType = MBProgressHUDAnimationFade;
		self.mode = MBProgressHUDModeIndeterminate;
		self.labelText = nil;
		self.detailsLabelText = nil;
		self.opacity = 0.8f;
		self.color = nil;
		self.labelFont = [UIFont boldSystemFontOfSize:kLabelFontSize];
		self.labelColor = [UIColor whiteColor];
		self.detailsLabelFont = [UIFont boldSystemFontOfSize:kDetailsLabelFontSize];
		self.detailsLabelColor = [UIColor whiteColor];
		self.activityIndicatorColor = [UIColor whiteColor];
		self.xOffset = 0.0f;
		self.yOffset = 0.0f;
		self.dimBackground = NO;
		self.margin = 20.0f;
		self.cornerRadius = 10.0f;
		self.graceTime = 0.0f;
		self.minShowTime = 0.0f;
		self.removeFromSuperViewOnHide = NO;
		self.minSize = CGSizeZero;
		self.square = NO;
		self.contentMode = UIViewContentModeCenter;
		self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin
								| UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;

		// Transparent background
		self.opaque = NO;
		self.backgroundColor = [UIColor clearColor];
		// Make it invisible for now
		self.alpha = 0.0f;
		
		taskInProgress = NO;
		rotationTransform = CGAffineTransformIdentity;
		
		[self setupLabels];
		[self updateIndicators];
		[self registerForKVO];
		[self registerForNotifications];
	}
	return self;
}

- (id)initWithView:(UIView *)view {
	NSAssert(view, @"View must not be nil.");
	return [self initWithFrame:view.bounds];
}

- (id)initWithWindow:(UIWindow *)window {
	return [self initWithView:window];
}

- (void)dealloc {
	[self unregisterFromNotifications];
	[self unregisterFromKVO];
#if !__has_feature(objc_arc)
	[color release];
	[indicator release];
	[label release];
	[detailsLabel release];
	[labelText release];
	[detailsLabelText release];
	[graceTimer release];
	[minShowTimer release];
	[showStarted release];
	[customView release];
	[labelFont release];
	[labelColor release];
	[detailsLabelFont release];
	[detailsLabelColor release];
#if NS_BLOCKS_AVAILABLE
	[completionBlock release];
#endif
	[super dealloc];
#endif
}

#pragma mark - Show & hide

- (void)show:(BOOL)animated {
	useAnimation = animated;
	// If the grace time is set postpone the HUD display
	if (self.graceTime > 0.0) {
		self.graceTimer = [NSTimer scheduledTimerWithTimeInterval:self.graceTime target:self 
						   selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO];
	} 
	// ... otherwise show the HUD imediately 
	else {
		[self setNeedsDisplay];
		[self showUsingAnimation:useAnimation];
	}
}

- (void)hide:(BOOL)animated {
	useAnimation = animated;
	// If the minShow time is set, calculate how long the hud was shown,
	// and pospone the hiding operation if necessary
	if (self.minShowTime > 0.0 && showStarted) {
		NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:showStarted];
		if (interv < self.minShowTime) {
			self.minShowTimer = [NSTimer scheduledTimerWithTimeInterval:(self.minShowTime - interv) target:self 
								selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO];
			return;
		} 
	}
	// ... otherwise hide the HUD immediately
	[self hideUsingAnimation:useAnimation];
}

- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay {
	[self performSelector:@selector(hideDelayed:) withObject:[NSNumber numberWithBool:animated] afterDelay:delay];
}

- (void)hideDelayed:(NSNumber *)animated {
	[self hide:[animated boolValue]];
}

#pragma mark - Timer callbacks

- (void)handleGraceTimer:(NSTimer *)theTimer {
	// Show the HUD only if the task is still running
	if (taskInProgress) {
		[self setNeedsDisplay];
		[self showUsingAnimation:useAnimation];
	}
}

- (void)handleMinShowTimer:(NSTimer *)theTimer {
	[self hideUsingAnimation:useAnimation];
}

#pragma mark - View Hierrarchy

- (BOOL)shouldPerformOrientationTransform {
	BOOL isPreiOS8 = NSFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_8_0;
	// prior to iOS8 code needs to take care of rotation if it is being added to the window
	return isPreiOS8 && [self.superview isKindOfClass:[UIWindow class]];
}

- (void)didMoveToSuperview {
	if ([self shouldPerformOrientationTransform]) {
		[self setTransformForCurrentOrientation:NO];
	}
}

#pragma mark - Internal show & hide operations

- (void)showUsingAnimation:(BOOL)animated {
	if (animated && animationType == MBProgressHUDAnimationZoomIn) {
		self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f));
	} else if (animated && animationType == MBProgressHUDAnimationZoomOut) {
		self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f));
	}
	self.showStarted = [NSDate date];
	// Fade in
	if (animated) {
		[UIView beginAnimations:nil context:NULL];
		[UIView setAnimationDuration:0.30];
		self.alpha = 1.0f;
		if (animationType == MBProgressHUDAnimationZoomIn || animationType == MBProgressHUDAnimationZoomOut) {
			self.transform = rotationTransform;
		}
		[UIView commitAnimations];
	}
	else {
		self.alpha = 1.0f;
	}
}

- (void)hideUsingAnimation:(BOOL)animated {
	// Fade out
	if (animated && showStarted) {
		[UIView beginAnimations:nil context:NULL];
		[UIView setAnimationDuration:0.30];
		[UIView setAnimationDelegate:self];
		[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
		// 0.02 prevents the hud from passing through touches during the animation the hud will get completely hidden
		// in the done method
		if (animationType == MBProgressHUDAnimationZoomIn) {
			self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f));
		} else if (animationType == MBProgressHUDAnimationZoomOut) {
			self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f));
		}

		self.alpha = 0.02f;
		[UIView commitAnimations];
	}
	else {
		self.alpha = 0.0f;
		[self done];
	}
	self.showStarted = nil;
}

- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void*)context {
	[self done];
}

- (void)done {
	[NSObject cancelPreviousPerformRequestsWithTarget:self];
	isFinished = YES;
	self.alpha = 0.0f;
	if (removeFromSuperViewOnHide) {
		[self removeFromSuperview];
	}
#if NS_BLOCKS_AVAILABLE
	if (self.completionBlock) {
		self.completionBlock();
		self.completionBlock = NULL;
	}
#endif
	if ([delegate respondsToSelector:@selector(hudWasHidden:)]) {
		[delegate performSelector:@selector(hudWasHidden:) withObject:self];
	}
}

#pragma mark - Threading

- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {
	methodForExecution = method;
	targetForExecution = MB_RETAIN(target);
	objectForExecution = MB_RETAIN(object);	
	// Launch execution in new thread
	self.taskInProgress = YES;
	[NSThread detachNewThreadSelector:@selector(launchExecution) toTarget:self withObject:nil];
	// Show HUD view
	[self show:animated];
}

#if NS_BLOCKS_AVAILABLE

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block {
	dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
	[self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL];
}

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(void (^)())completion {
	dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
	[self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:completion];
}

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue {
	[self showAnimated:animated whileExecutingBlock:block onQueue:queue	completionBlock:NULL];
}

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue
	 completionBlock:(MBProgressHUDCompletionBlock)completion {
	self.taskInProgress = YES;
	self.completionBlock = completion;
	dispatch_async(queue, ^(void) {
		block();
		dispatch_async(dispatch_get_main_queue(), ^(void) {
			[self cleanUp];
		});
	});
	[self show:animated];
}

#endif

- (void)launchExecution {
	@autoreleasepool {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
		// Start executing the requested task
		[targetForExecution performSelector:methodForExecution withObject:objectForExecution];
#pragma clang diagnostic pop
		// Task completed, update view in main thread (note: view operations should
		// be done only in the main thread)
		[self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO];
	}
}

- (void)cleanUp {
	taskInProgress = NO;
#if !__has_feature(objc_arc)
	[targetForExecution release];
	[objectForExecution release];
#else
	targetForExecution = nil;
	objectForExecution = nil;
#endif
	[self hide:useAnimation];
}

#pragma mark - UI

- (void)setupLabels {
	label = [[UILabel alloc] initWithFrame:self.bounds];
	label.adjustsFontSizeToFitWidth = NO;
	label.textAlignment = MBLabelAlignmentCenter;
	label.opaque = NO;
	label.backgroundColor = [UIColor clearColor];
	label.textColor = self.labelColor;
	label.font = self.labelFont;
	label.text = self.labelText;
	[self addSubview:label];
	
	detailsLabel = [[UILabel alloc] initWithFrame:self.bounds];
	detailsLabel.font = self.detailsLabelFont;
	detailsLabel.adjustsFontSizeToFitWidth = NO;
	detailsLabel.textAlignment = MBLabelAlignmentCenter;
	detailsLabel.opaque = NO;
	detailsLabel.backgroundColor = [UIColor clearColor];
	detailsLabel.textColor = self.detailsLabelColor;
	detailsLabel.numberOfLines = 0;
	detailsLabel.font = self.detailsLabelFont;
	detailsLabel.text = self.detailsLabelText;
	[self addSubview:detailsLabel];
}

- (void)updateIndicators {
	
	BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]];
	BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]];
	
	if (mode == MBProgressHUDModeIndeterminate) {
		if (!isActivityIndicator) {
			// Update to indeterminate indicator
			[indicator removeFromSuperview];
			self.indicator = MB_AUTORELEASE([[UIActivityIndicatorView alloc]
											 initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]);
			[(UIActivityIndicatorView *)indicator startAnimating];
			[self addSubview:indicator];
		}
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
		[(UIActivityIndicatorView *)indicator setColor:self.activityIndicatorColor];
#endif
	}
	else if (mode == MBProgressHUDModeDeterminateHorizontalBar) {
		// Update to bar determinate indicator
		[indicator removeFromSuperview];
		self.indicator = MB_AUTORELEASE([[MBBarProgressView alloc] init]);
		[self addSubview:indicator];
	}
	else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) {
		if (!isRoundIndicator) {
			// Update to determinante indicator
			[indicator removeFromSuperview];
			self.indicator = MB_AUTORELEASE([[MBRoundProgressView alloc] init]);
			[self addSubview:indicator];
		}
		if (mode == MBProgressHUDModeAnnularDeterminate) {
			[(MBRoundProgressView *)indicator setAnnular:YES];
		}
	} 
	else if (mode == MBProgressHUDModeCustomView && customView != indicator) {
		// Update custom view indicator
		[indicator removeFromSuperview];
		self.indicator = customView;
		[self addSubview:indicator];
	} else if (mode == MBProgressHUDModeText) {
		[indicator removeFromSuperview];
		self.indicator = nil;
	}
}

#pragma mark - Layout

- (void)layoutSubviews {
	[super layoutSubviews];
	
	// Entirely cover the parent view
	UIView *parent = self.superview;
	if (parent) {
		self.frame = parent.bounds;
	}
	CGRect bounds = self.bounds;
	
	// Determine the total widt and height needed
	CGFloat maxWidth = bounds.size.width - 4 * margin;
	CGSize totalSize = CGSizeZero;
	
	CGRect indicatorF = indicator.bounds;
	indicatorF.size.width = MIN(indicatorF.size.width, maxWidth);
	totalSize.width = MAX(totalSize.width, indicatorF.size.width);
	totalSize.height += indicatorF.size.height;
	
	CGSize labelSize = MB_TEXTSIZE(label.text, label.font);
	labelSize.width = MIN(labelSize.width, maxWidth);
	totalSize.width = MAX(totalSize.width, labelSize.width);
	totalSize.height += labelSize.height;
	if (labelSize.height > 0.f && indicatorF.size.height > 0.f) {
		totalSize.height += kPadding;
	}

	CGFloat remainingHeight = bounds.size.height - totalSize.height - kPadding - 4 * margin; 
	CGSize maxSize = CGSizeMake(maxWidth, remainingHeight);
	CGSize detailsLabelSize = MB_MULTILINE_TEXTSIZE(detailsLabel.text, detailsLabel.font, maxSize, detailsLabel.lineBreakMode);
	totalSize.width = MAX(totalSize.width, detailsLabelSize.width);
	totalSize.height += detailsLabelSize.height;
	if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) {
		totalSize.height += kPadding;
	}
	
	totalSize.width += 2 * margin;
	totalSize.height += 2 * margin;
	
	// Position elements
	CGFloat yPos = round(((bounds.size.height - totalSize.height) / 2)) + margin + yOffset;
	CGFloat xPos = xOffset;
	indicatorF.origin.y = yPos;
	indicatorF.origin.x = round((bounds.size.width - indicatorF.size.width) / 2) + xPos;
	indicator.frame = indicatorF;
	yPos += indicatorF.size.height;
	
	if (labelSize.height > 0.f && indicatorF.size.height > 0.f) {
		yPos += kPadding;
	}
	CGRect labelF;
	labelF.origin.y = yPos;
	labelF.origin.x = round((bounds.size.width - labelSize.width) / 2) + xPos;
	labelF.size = labelSize;
	label.frame = labelF;
	yPos += labelF.size.height;
	
	if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) {
		yPos += kPadding;
	}
	CGRect detailsLabelF;
	detailsLabelF.origin.y = yPos;
	detailsLabelF.origin.x = round((bounds.size.width - detailsLabelSize.width) / 2) + xPos;
	detailsLabelF.size = detailsLabelSize;
	detailsLabel.frame = detailsLabelF;
	
	// Enforce minsize and quare rules
	if (square) {
		CGFloat max = MAX(totalSize.width, totalSize.height);
		if (max <= bounds.size.width - 2 * margin) {
			totalSize.width = max;
		}
		if (max <= bounds.size.height - 2 * margin) {
			totalSize.height = max;
		}
	}
	if (totalSize.width < minSize.width) {
		totalSize.width = minSize.width;
	} 
	if (totalSize.height < minSize.height) {
		totalSize.height = minSize.height;
	}
	
	size = totalSize;
}

#pragma mark BG Drawing

- (void)drawRect:(CGRect)rect {
	
	CGContextRef context = UIGraphicsGetCurrentContext();
	UIGraphicsPushContext(context);

	if (self.dimBackground) {
		//Gradient colours
		size_t gradLocationsNum = 2;
		CGFloat gradLocations[2] = {0.0f, 1.0f};
		CGFloat gradColors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f}; 
		CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
		CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationsNum);
		CGColorSpaceRelease(colorSpace);
		//Gradient center
		CGPoint gradCenter= CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
		//Gradient radius
		float gradRadius = MIN(self.bounds.size.width , self.bounds.size.height) ;
		//Gradient draw
		CGContextDrawRadialGradient (context, gradient, gradCenter,
									 0, gradCenter, gradRadius,
									 kCGGradientDrawsAfterEndLocation);
		CGGradientRelease(gradient);
	}

	// Set background rect color
	if (self.color) {
		CGContextSetFillColorWithColor(context, self.color.CGColor);
	} else {
		CGContextSetGrayFillColor(context, 0.0f, self.opacity);
	}

	
	// Center HUD
	CGRect allRect = self.bounds;
	// Draw rounded HUD backgroud rect
	CGRect boxRect = CGRectMake(round((allRect.size.width - size.width) / 2) + self.xOffset,
								round((allRect.size.height - size.height) / 2) + self.yOffset, size.width, size.height);
	float radius = self.cornerRadius;
	CGContextBeginPath(context);
	CGContextMoveToPoint(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect));
	CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMinY(boxRect) + radius, radius, 3 * (float)M_PI / 2, 0, 0);
	CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMaxY(boxRect) - radius, radius, 0, (float)M_PI / 2, 0);
	CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMaxY(boxRect) - radius, radius, (float)M_PI / 2, (float)M_PI, 0);
	CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect) + radius, radius, (float)M_PI, 3 * (float)M_PI / 2, 0);
	CGContextClosePath(context);
	CGContextFillPath(context);

	UIGraphicsPopContext();
}

#pragma mark - KVO

- (void)registerForKVO {
	for (NSString *keyPath in [self observableKeypaths]) {
		[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];
	}
}

- (void)unregisterFromKVO {
	for (NSString *keyPath in [self observableKeypaths]) {
		[self removeObserver:self forKeyPath:keyPath];
	}
}

- (NSArray *)observableKeypaths {
	return [NSArray arrayWithObjects:@"mode", @"customView", @"labelText", @"labelFont", @"labelColor",
			@"detailsLabelText", @"detailsLabelFont", @"detailsLabelColor", @"progress", @"activityIndicatorColor", nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	if (![NSThread isMainThread]) {
		[self performSelectorOnMainThread:@selector(updateUIForKeypath:) withObject:keyPath waitUntilDone:NO];
	} else {
		[self updateUIForKeypath:keyPath];
	}
}

- (void)updateUIForKeypath:(NSString *)keyPath {
	if ([keyPath isEqualToString:@"mode"] || [keyPath isEqualToString:@"customView"] ||
		[keyPath isEqualToString:@"activityIndicatorColor"]) {
		[self updateIndicators];
	} else if ([keyPath isEqualToString:@"labelText"]) {
		label.text = self.labelText;
	} else if ([keyPath isEqualToString:@"labelFont"]) {
		label.font = self.labelFont;
	} else if ([keyPath isEqualToString:@"labelColor"]) {
		label.textColor = self.labelColor;
	} else if ([keyPath isEqualToString:@"detailsLabelText"]) {
		detailsLabel.text = self.detailsLabelText;
	} else if ([keyPath isEqualToString:@"detailsLabelFont"]) {
		detailsLabel.font = self.detailsLabelFont;
	} else if ([keyPath isEqualToString:@"detailsLabelColor"]) {
		detailsLabel.textColor = self.detailsLabelColor;
	} else if ([keyPath isEqualToString:@"progress"]) {
		if ([indicator respondsToSelector:@selector(setProgress:)]) {
			[(id)indicator setValue:@(progress) forKey:@"progress"];
		}
		return;
	}
	[self setNeedsLayout];
	[self setNeedsDisplay];
}

#pragma mark - Notifications

- (void)registerForNotifications {
	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

	[nc addObserver:self selector:@selector(statusBarOrientationDidChange:)
			   name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

- (void)unregisterFromNotifications {
	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
	[nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

- (void)statusBarOrientationDidChange:(NSNotification *)notification {
	UIView *superview = self.superview;
	if (!superview) {
		return;
	} else if ([self shouldPerformOrientationTransform]) {
		[self setTransformForCurrentOrientation:YES];
	} else {
		self.frame = self.superview.bounds;
		[self setNeedsDisplay];
	}
}

- (void)setTransformForCurrentOrientation:(BOOL)animated {
	// Stay in sync with the superview
	if (self.superview) {
		self.bounds = self.superview.bounds;
		[self setNeedsDisplay];
	}
	
	UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
	CGFloat radians = 0;
	if (UIInterfaceOrientationIsLandscape(orientation)) {
		if (orientation == UIInterfaceOrientationLandscapeLeft) { radians = -(CGFloat)M_PI_2; } 
		else { radians = (CGFloat)M_PI_2; }
		// Window coordinates differ!
		self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width);
	} else {
		if (orientation == UIInterfaceOrientationPortraitUpsideDown) { radians = (CGFloat)M_PI; } 
		else { radians = 0; }
	}
	rotationTransform = CGAffineTransformMakeRotation(radians);
	
	if (animated) {
		[UIView beginAnimations:nil context:nil];
		[UIView setAnimationDuration:0.3];
	}
	[self setTransform:rotationTransform];
	if (animated) {
		[UIView commitAnimations];
	}
}

@end


@implementation MBRoundProgressView

#pragma mark - Lifecycle

- (id)init {
	return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)];
}

- (id)initWithFrame:(CGRect)frame {
	self = [super initWithFrame:frame];
	if (self) {
		self.backgroundColor = [UIColor clearColor];
		self.opaque = NO;
		_progress = 0.f;
		_annular = NO;
		_progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f];
		_backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f];
		[self registerForKVO];
	}
	return self;
}

- (void)dealloc {
	[self unregisterFromKVO];
#if !__has_feature(objc_arc)
	[_progressTintColor release];
	[_backgroundTintColor release];
	[super dealloc];
#endif
}

#pragma mark - Drawing

- (void)drawRect:(CGRect)rect {
	
	CGRect allRect = self.bounds;
	CGRect circleRect = CGRectInset(allRect, 2.0f, 2.0f);
	CGContextRef context = UIGraphicsGetCurrentContext();
	
	if (_annular) {
		// Draw background
		BOOL isPreiOS7 = NSFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0;
		CGFloat lineWidth = isPreiOS7 ? 5.f : 2.f;
		UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath];
		processBackgroundPath.lineWidth = lineWidth;
		processBackgroundPath.lineCapStyle = kCGLineCapButt;
		CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
		CGFloat radius = (self.bounds.size.width - lineWidth)/2;
		CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees
		CGFloat endAngle = (2 * (float)M_PI) + startAngle;
		[processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
		[_backgroundTintColor set];
		[processBackgroundPath stroke];
		// Draw progress
		UIBezierPath *processPath = [UIBezierPath bezierPath];
		processPath.lineCapStyle = isPreiOS7 ? kCGLineCapRound : kCGLineCapSquare;
		processPath.lineWidth = lineWidth;
		endAngle = (self.progress * 2 * (float)M_PI) + startAngle;
		[processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
		[_progressTintColor set];
		[processPath stroke];
	} else {
		// Draw background
		[_progressTintColor setStroke];
		[_backgroundTintColor setFill];
		CGContextSetLineWidth(context, 2.0f);
		CGContextFillEllipseInRect(context, circleRect);
		CGContextStrokeEllipseInRect(context, circleRect);
		// Draw progress
		CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2);
		CGFloat radius = (allRect.size.width - 4) / 2;
		CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees
		CGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle;
		CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); // white
		CGContextMoveToPoint(context, center.x, center.y);
		CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
		CGContextClosePath(context);
		CGContextFillPath(context);
	}
}

#pragma mark - KVO

- (void)registerForKVO {
	for (NSString *keyPath in [self observableKeypaths]) {
		[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];
	}
}

- (void)unregisterFromKVO {
	for (NSString *keyPath in [self observableKeypaths]) {
		[self removeObserver:self forKeyPath:keyPath];
	}
}

- (NSArray *)observableKeypaths {
	return [NSArray arrayWithObjects:@"progressTintColor", @"backgroundTintColor", @"progress", @"annular", nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	[self setNeedsDisplay];
}

@end


@implementation MBBarProgressView

#pragma mark - Lifecycle

- (id)init {
	return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)];
}

- (id)initWithFrame:(CGRect)frame {
	self = [super initWithFrame:frame];
	if (self) {
		_progress = 0.f;
		_lineColor = [UIColor whiteColor];
		_progressColor = [UIColor whiteColor];
		_progressRemainingColor = [UIColor clearColor];
		self.backgroundColor = [UIColor clearColor];
		self.opaque = NO;
		[self registerForKVO];
	}
	return self;
}

- (void)dealloc {
	[self unregisterFromKVO];
#if !__has_feature(objc_arc)
	[_lineColor release];
	[_progressColor release];
	[_progressRemainingColor release];
	[super dealloc];
#endif
}

#pragma mark - Drawing

- (void)drawRect:(CGRect)rect {
	CGContextRef context = UIGraphicsGetCurrentContext();
	
	CGContextSetLineWidth(context, 2);
	CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]);
	CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]);
	
	// Draw background
	float radius = (rect.size.height / 2) - 2;
	CGContextMoveToPoint(context, 2, rect.size.height/2);
	CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius);
	CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2);
	CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius);
	CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius);
	CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2);
	CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius);
	CGContextFillPath(context);
	
	// Draw border
	CGContextMoveToPoint(context, 2, rect.size.height/2);
	CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius);
	CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2);
	CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius);
	CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius);
	CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2);
	CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius);
	CGContextStrokePath(context);
	
	CGContextSetFillColorWithColor(context, [_progressColor CGColor]);
	radius = radius - 2;
	float amount = self.progress * rect.size.width;
	
	// Progress in the middle area
	if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) {
		CGContextMoveToPoint(context, 4, rect.size.height/2);
		CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius);
		CGContextAddLineToPoint(context, amount, 4);
		CGContextAddLineToPoint(context, amount, radius + 4);
		
		CGContextMoveToPoint(context, 4, rect.size.height/2);
		CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius);
		CGContextAddLineToPoint(context, amount, rect.size.height - 4);
		CGContextAddLineToPoint(context, amount, radius + 4);
		
		CGContextFillPath(context);
	}
	
	// Progress in the right arc
	else if (amount > radius + 4) {
		float x = amount - (rect.size.width - radius - 4);

		CGContextMoveToPoint(context, 4, rect.size.height/2);
		CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius);
		CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4);
		float angle = -acos(x/radius);
		if (isnan(angle)) angle = 0;
		CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0);
		CGContextAddLineToPoint(context, amount, rect.size.height/2);

		CGContextMoveToPoint(context, 4, rect.size.height/2);
		CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius);
		CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4);
		angle = acos(x/radius);
		if (isnan(angle)) angle = 0;
		CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1);
		CGContextAddLineToPoint(context, amount, rect.size.height/2);
		
		CGContextFillPath(context);
	}
	
	// Progress is in the left arc
	else if (amount < radius + 4 && amount > 0) {
		CGContextMoveToPoint(context, 4, rect.size.height/2);
		CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius);
		CGContextAddLineToPoint(context, radius + 4, rect.size.height/2);

		CGContextMoveToPoint(context, 4, rect.size.height/2);
		CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius);
		CGContextAddLineToPoint(context, radius + 4, rect.size.height/2);
		
		CGContextFillPath(context);
	}
}

#pragma mark - KVO

- (void)registerForKVO {
	for (NSString *keyPath in [self observableKeypaths]) {
		[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];
	}
}

- (void)unregisterFromKVO {
	for (NSString *keyPath in [self observableKeypaths]) {
		[self removeObserver:self forKeyPath:keyPath];
	}
}

- (NSArray *)observableKeypaths {
	return [NSArray arrayWithObjects:@"lineColor", @"progressRemainingColor", @"progressColor", @"progress", nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	[self setNeedsDisplay];
}

@end


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/ViewController.h
================================================
//
//  ViewController.h
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController


@end



================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/ViewController.m
================================================
//
//  ViewController.m
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. All rights reserved.
//

#import "ViewController.h"
#import "CYPasswordView.h"
#import "MBProgressHUD+MJ.h"

#define kRequestTime 3.0f
#define kDelay 1.0f

@interface ViewController ()

@property (nonatomic, strong) CYPasswordView *passwordView;

@end

@implementation ViewController

static BOOL flag = NO;

- (void)viewDidLoad {
    [super viewDidLoad];
    /** 注册取消按钮点击的通知 */
    [CYNotificationCenter addObserver:self selector:@selector(cancel) name:CYPasswordViewCancleButtonClickNotification object:nil];
    [CYNotificationCenter addObserver:self selector:@selector(forgetPWD) name:CYPasswordViewForgetPWDButtonClickNotification object:nil];
}

- (void)dealloc {
    CYLog(@"cy =========== %@:我走了", [self class]);
}

- (void)cancel {
    CYLog(@"关闭密码框");
    [MBProgressHUD showSuccess:@"关闭密码框"];
}

- (void)forgetPWD {
    CYLog(@"忘记密码");
    [MBProgressHUD showSuccess:@"忘记密码"];
}

- (IBAction)showPasswordView:(id)sender {
    __weak ViewController *weakSelf = self;
    self.passwordView = [[CYPasswordView alloc] init];
    self.passwordView.title = @"输入交易密码";
    self.passwordView.loadingText = @"提交中...";
    [self.passwordView showInView:self.view.window];

    self.passwordView.finish = ^(NSString *password) {
        [weakSelf.passwordView hideKeyboard];
        [weakSelf.passwordView startLoading];
        CYLog(@"cy ========= 发送网络请求  pwd=%@", password);
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kRequestTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            flag = !flag;
            if (flag) {
                CYLog(@"申购成功,跳转到成功页");
                [MBProgressHUD showSuccess:@"申购成功,做一些处理"];
                [weakSelf.passwordView requestComplete:YES message:@"申购成功,做一些处理"];
                [weakSelf.passwordView stopLoading];
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [weakSelf.passwordView hide];
                });
            } else {
                CYLog(@"申购失败,跳转到失败页");
                [MBProgressHUD showError:@"申购失败,做一些处理"];
                [weakSelf.passwordView requestComplete:NO message:@"申购失败,做一些处理"];
                [weakSelf.passwordView stopLoading];
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [weakSelf.passwordView hide];
                });

            }
            
        });
    };
}

@end


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo/main.m
================================================
//
//  main.m
//  CYPasswordViewDemo
//
//  Created by cheny on 15/10/8.
//  Copyright © 2015年 zhssit. 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: CYPasswordViewDemo/CYPasswordViewDemo.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		18A5355D1F62F6B800A23CE9 /* CYConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 18A535531F62F6B800A23CE9 /* CYConst.m */; };
		18A5355E1F62F6B800A23CE9 /* CYPasswordInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18A535551F62F6B800A23CE9 /* CYPasswordInputView.m */; };
		18A5355F1F62F6B800A23CE9 /* CYPasswordView.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 18A535561F62F6B800A23CE9 /* CYPasswordView.bundle */; };
		18A535601F62F6B800A23CE9 /* CYPasswordView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18A535581F62F6B800A23CE9 /* CYPasswordView.m */; };
		18A535611F62F6B800A23CE9 /* NSBundle+CYPasswordView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18A5355A1F62F6B800A23CE9 /* NSBundle+CYPasswordView.m */; };
		18A535621F62F6B800A23CE9 /* UIView+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 18A5355C1F62F6B800A23CE9 /* UIView+Extension.m */; };
		18C053A41BD205FE008889D3 /* MBProgressHUD+MJ.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C053A01BD205FE008889D3 /* MBProgressHUD+MJ.m */; };
		18C053A51BD205FE008889D3 /* MBProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 18C053A11BD205FE008889D3 /* MBProgressHUD.bundle */; };
		18C053A61BD205FE008889D3 /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C053A31BD205FE008889D3 /* MBProgressHUD.m */; };
		9AE0840E1BC6B61100BA6950 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AE0840D1BC6B61100BA6950 /* main.m */; };
		9AE084111BC6B61100BA6950 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AE084101BC6B61100BA6950 /* AppDelegate.m */; };
		9AE084141BC6B61100BA6950 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AE084131BC6B61100BA6950 /* ViewController.m */; };
		9AE084171BC6B61100BA6950 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9AE084151BC6B61100BA6950 /* Main.storyboard */; };
		9AE084191BC6B61100BA6950 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9AE084181BC6B61100BA6950 /* Assets.xcassets */; };
		9AE0841C1BC6B61100BA6950 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9AE0841A1BC6B61100BA6950 /* LaunchScreen.storyboard */; };
		F72E80F72518B71E00BAAACE /* UIDevice+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = F72E80F62518B71E00BAAACE /* UIDevice+Extension.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		18A535521F62F6B800A23CE9 /* CYConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYConst.h; sourceTree = "<group>"; };
		18A535531F62F6B800A23CE9 /* CYConst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYConst.m; sourceTree = "<group>"; };
		18A535541F62F6B800A23CE9 /* CYPasswordInputView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYPasswordInputView.h; sourceTree = "<group>"; };
		18A535551F62F6B800A23CE9 /* CYPasswordInputView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYPasswordInputView.m; sourceTree = "<group>"; };
		18A535561F62F6B800A23CE9 /* CYPasswordView.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = CYPasswordView.bundle; sourceTree = "<group>"; };
		18A535571F62F6B800A23CE9 /* CYPasswordView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYPasswordView.h; sourceTree = "<group>"; };
		18A535581F62F6B800A23CE9 /* CYPasswordView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYPasswordView.m; sourceTree = "<group>"; };
		18A535591F62F6B800A23CE9 /* NSBundle+CYPasswordView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+CYPasswordView.h"; sourceTree = "<group>"; };
		18A5355A1F62F6B800A23CE9 /* NSBundle+CYPasswordView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+CYPasswordView.m"; sourceTree = "<group>"; };
		18A5355B1F62F6B800A23CE9 /* UIView+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Extension.h"; sourceTree = "<group>"; };
		18A5355C1F62F6B800A23CE9 /* UIView+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Extension.m"; sourceTree = "<group>"; };
		18C0539F1BD205FE008889D3 /* MBProgressHUD+MJ.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD+MJ.h"; sourceTree = "<group>"; };
		18C053A01BD205FE008889D3 /* MBProgressHUD+MJ.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MBProgressHUD+MJ.m"; sourceTree = "<group>"; };
		18C053A11BD205FE008889D3 /* MBProgressHUD.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MBProgressHUD.bundle; sourceTree = "<group>"; };
		18C053A21BD205FE008889D3 /* MBProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBProgressHUD.h; sourceTree = "<group>"; };
		18C053A31BD205FE008889D3 /* MBProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBProgressHUD.m; sourceTree = "<group>"; };
		9AE084091BC6B61100BA6950 /* CYPasswordViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CYPasswordViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
		9AE0840D1BC6B61100BA6950 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		9AE0840F1BC6B61100BA6950 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		9AE084101BC6B61100BA6950 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		9AE084121BC6B61100BA6950 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
		9AE084131BC6B61100BA6950 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
		9AE084161BC6B61100BA6950 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		9AE084181BC6B61100BA6950 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		9AE0841B1BC6B61100BA6950 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		9AE0841D1BC6B61100BA6950 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		F72E80F52518B6E000BAAACE /* UIDevice+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIDevice+Extension.h"; sourceTree = "<group>"; };
		F72E80F62518B71E00BAAACE /* UIDevice+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+Extension.m"; sourceTree = "<group>"; };
/* End PBXFileReference section */

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

/* Begin PBXGroup section */
		18A535511F62F6B800A23CE9 /* CYPasswordView */ = {
			isa = PBXGroup;
			children = (
				18A535521F62F6B800A23CE9 /* CYConst.h */,
				18A535531F62F6B800A23CE9 /* CYConst.m */,
				18A535541F62F6B800A23CE9 /* CYPasswordInputView.h */,
				18A535551F62F6B800A23CE9 /* CYPasswordInputView.m */,
				18A535561F62F6B800A23CE9 /* CYPasswordView.bundle */,
				18A535571F62F6B800A23CE9 /* CYPasswordView.h */,
				18A535581F62F6B800A23CE9 /* CYPasswordView.m */,
				18A535591F62F6B800A23CE9 /* NSBundle+CYPasswordView.h */,
				18A5355A1F62F6B800A23CE9 /* NSBundle+CYPasswordView.m */,
				18A5355B1F62F6B800A23CE9 /* UIView+Extension.h */,
				18A5355C1F62F6B800A23CE9 /* UIView+Extension.m */,
				F72E80F52518B6E000BAAACE /* UIDevice+Extension.h */,
				F72E80F62518B71E00BAAACE /* UIDevice+Extension.m */,
			);
			name = CYPasswordView;
			path = ../../CYPasswordView;
			sourceTree = "<group>";
		};
		18C0539E1BD205FE008889D3 /* MBProgressHUD */ = {
			isa = PBXGroup;
			children = (
				18C0539F1BD205FE008889D3 /* MBProgressHUD+MJ.h */,
				18C053A01BD205FE008889D3 /* MBProgressHUD+MJ.m */,
				18C053A11BD205FE008889D3 /* MBProgressHUD.bundle */,
				18C053A21BD205FE008889D3 /* MBProgressHUD.h */,
				18C053A31BD205FE008889D3 /* MBProgressHUD.m */,
			);
			path = MBProgressHUD;
			sourceTree = "<group>";
		};
		9AE084001BC6B61100BA6950 = {
			isa = PBXGroup;
			children = (
				9AE0840B1BC6B61100BA6950 /* CYPasswordViewDemo */,
				9AE0840A1BC6B61100BA6950 /* Products */,
			);
			sourceTree = "<group>";
		};
		9AE0840A1BC6B61100BA6950 /* Products */ = {
			isa = PBXGroup;
			children = (
				9AE084091BC6B61100BA6950 /* CYPasswordViewDemo.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		9AE0840B1BC6B61100BA6950 /* CYPasswordViewDemo */ = {
			isa = PBXGroup;
			children = (
				18A535511F62F6B800A23CE9 /* CYPasswordView */,
				9AE0840F1BC6B61100BA6950 /* AppDelegate.h */,
				9AE084101BC6B61100BA6950 /* AppDelegate.m */,
				9AE084121BC6B61100BA6950 /* ViewController.h */,
				9AE084131BC6B61100BA6950 /* ViewController.m */,
				9AE084151BC6B61100BA6950 /* Main.storyboard */,
				18C0539E1BD205FE008889D3 /* MBProgressHUD */,
				9AE084181BC6B61100BA6950 /* Assets.xcassets */,
				9AE0841A1BC6B61100BA6950 /* LaunchScreen.storyboard */,
				9AE0841D1BC6B61100BA6950 /* Info.plist */,
				9AE0840C1BC6B61100BA6950 /* Supporting Files */,
			);
			path = CYPasswordViewDemo;
			sourceTree = "<group>";
		};
		9AE0840C1BC6B61100BA6950 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				9AE0840D1BC6B61100BA6950 /* main.m */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		9AE084081BC6B61100BA6950 /* CYPasswordViewDemo */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 9AE084201BC6B61100BA6950 /* Build configuration list for PBXNativeTarget "CYPasswordViewDemo" */;
			buildPhases = (
				9AE084051BC6B61100BA6950 /* Sources */,
				9AE084061BC6B61100BA6950 /* Frameworks */,
				9AE084071BC6B61100BA6950 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = CYPasswordViewDemo;
			productName = CYPasswordViewDemo;
			productReference = 9AE084091BC6B61100BA6950 /* CYPasswordViewDemo.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		9AE084011BC6B61100BA6950 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				CLASSPREFIX = CY;
				LastUpgradeCheck = 0700;
				ORGANIZATIONNAME = zhssit;
				TargetAttributes = {
					9AE084081BC6B61100BA6950 = {
						CreatedOnToolsVersion = 7.0;
					};
				};
			};
			buildConfigurationList = 9AE084041BC6B61100BA6950 /* Build configuration list for PBXProject "CYPasswordViewDemo" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				English,
				en,
				Base,
			);
			mainGroup = 9AE084001BC6B61100BA6950;
			productRefGroup = 9AE0840A1BC6B61100BA6950 /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				9AE084081BC6B61100BA6950 /* CYPasswordViewDemo */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		9AE084071BC6B61100BA6950 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				9AE0841C1BC6B61100BA6950 /* LaunchScreen.storyboard in Resources */,
				9AE084191BC6B61100BA6950 /* Assets.xcassets in Resources */,
				18C053A51BD205FE008889D3 /* MBProgressHUD.bundle in Resources */,
				9AE084171BC6B61100BA6950 /* Main.storyboard in Resources */,
				18A5355F1F62F6B800A23CE9 /* CYPasswordView.bundle in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		9AE084051BC6B61100BA6950 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				18A535621F62F6B800A23CE9 /* UIView+Extension.m in Sources */,
				18A5355E1F62F6B800A23CE9 /* CYPasswordInputView.m in Sources */,
				9AE084141BC6B61100BA6950 /* ViewController.m in Sources */,
				18C053A61BD205FE008889D3 /* MBProgressHUD.m in Sources */,
				18C053A41BD205FE008889D3 /* MBProgressHUD+MJ.m in Sources */,
				9AE084111BC6B61100BA6950 /* AppDelegate.m in Sources */,
				18A535611F62F6B800A23CE9 /* NSBundle+CYPasswordView.m in Sources */,
				F72E80F72518B71E00BAAACE /* UIDevice+Extension.m in Sources */,
				18A535601F62F6B800A23CE9 /* CYPasswordView.m in Sources */,
				9AE0840E1BC6B61100BA6950 /* main.m in Sources */,
				18A5355D1F62F6B800A23CE9 /* CYConst.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
		9AE084151BC6B61100BA6950 /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				9AE084161BC6B61100BA6950 /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
		9AE0841A1BC6B61100BA6950 /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				9AE0841B1BC6B61100BA6950 /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		9AE0841E1BC6B61100BA6950 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				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 = 9.0;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
			};
			name = Debug;
		};
		9AE0841F1BC6B61100BA6950 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "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 = gnu99;
				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 = 9.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		9AE084211BC6B61100BA6950 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				INFOPLIST_FILE = CYPasswordViewDemo/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.develop.CYPasswordViewDemo;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		9AE084221BC6B61100BA6950 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				INFOPLIST_FILE = CYPasswordViewDemo/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.develop.CYPasswordViewDemo;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		9AE084041BC6B61100BA6950 /* Build configuration list for PBXProject "CYPasswordViewDemo" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				9AE0841E1BC6B61100BA6950 /* Debug */,
				9AE0841F1BC6B61100BA6950 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		9AE084201BC6B61100BA6950 /* Build configuration list for PBXNativeTarget "CYPasswordViewDemo" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				9AE084211BC6B61100BA6950 /* Debug */,
				9AE084221BC6B61100BA6950 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 9AE084011BC6B61100BA6950 /* Project object */;
}


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


================================================
FILE: CYPasswordViewDemo/CYPasswordViewDemo.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: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 cheny

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
================================================
## CYPasswordView
---
`CYPasswordView`是一个模仿支付宝输入支付密码的密码框。
### 一、说明
---
* `CYPasswordView`是一个简单且实用的输入密码框
* 具体用法主要参考Demo程序

### 二、使用方法
---
#### 使用 CocoaPods 
`pod 'CYPasswordView'`

#### 手动导入文件
1. 将`CYPasswordView`文件夹添加到项目中
2. 导入主头文件`#import "CYPasswordView.h"`

### 三、部分API的介绍
---
* 实例化`CYPasswordView`对象
``` objc
[[CYPasswordView alloc] init];
```
* 弹出密码框
``` objc
- (void)showInView:(UIView *)view;
```

* 密码输入完成的回调
``` objc
@property (nonatomic, copy) void (^finish) (NSString *password);
```
* 隐藏键盘
``` objc
- (void)hidenKeyboard;
```
* 隐藏密码框
``` objc
- (void)hide;
```
* 开始加载(发送网络请求时,加载动画)
``` objc
- (void)startLoading;
```

* 加载完成(暂停动画)
``` objc
- (void)stopLoading;
```

* 请求完成
``` objc
- (void)requestComplete:(BOOL)state;
- (void)requestComplete:(BOOL)state message:(NSString *)message;
```

* 设置对话框标题
``` objc
@property (nonatomic, copy) NSString *title;
```

### 四、效果示例
---
![CYPasswordView](https://github.com/chernyog/CYPasswordView/blob/master/CYPasswordViewDemo/CYPasswordViewDemo/CYPasswordViewDemo.gif "CYPasswordView示例")
Download .txt
gitextract_n2axo8ji/

├── .gitignore
├── CYPasswordView/
│   ├── CYConst.h
│   ├── CYConst.m
│   ├── CYPasswordInputView.h
│   ├── CYPasswordInputView.m
│   ├── CYPasswordView.h
│   ├── CYPasswordView.m
│   ├── NSBundle+CYPasswordView.h
│   ├── NSBundle+CYPasswordView.m
│   ├── UIDevice+Extension.h
│   ├── UIDevice+Extension.m
│   ├── UIView+Extension.h
│   └── UIView+Extension.m
├── CYPasswordView.podspec
├── CYPasswordViewDemo/
│   ├── CYPasswordViewDemo/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── Contents.json
│   │   │   └── arrow.imageset/
│   │   │       └── Contents.json
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Info.plist
│   │   ├── MBProgressHUD/
│   │   │   ├── MBProgressHUD+MJ.h
│   │   │   ├── MBProgressHUD+MJ.m
│   │   │   ├── MBProgressHUD.h
│   │   │   └── MBProgressHUD.m
│   │   ├── ViewController.h
│   │   ├── ViewController.m
│   │   └── main.m
│   └── CYPasswordViewDemo.xcodeproj/
│       ├── project.pbxproj
│       └── project.xcworkspace/
│           ├── contents.xcworkspacedata
│           └── xcshareddata/
│               └── IDEWorkspaceChecks.plist
├── LICENSE
└── README.md
Download .txt
SYMBOL INDEX (2 symbols across 1 files)

FILE: CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD.h
  type MBProgressHUDMode (line 36) | typedef enum {
  type MBProgressHUDAnimation (line 51) | typedef enum {
Condensed preview — 34 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (150K chars).
[
  {
    "path": ".gitignore",
    "chars": 494,
    "preview": "# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!defau"
  },
  {
    "path": "CYPasswordView/CYConst.h",
    "chars": 2116,
    "preview": "#import <UIKit/UIKit.h>\n\n// 日志输出\n#ifdef DEBUG\n#define CYLog(...) NSLog(__VA_ARGS__)\n#else\n#define CYLog(...)\n#endif\n\n// "
  },
  {
    "path": "CYPasswordView/CYConst.m",
    "chars": 1327,
    "preview": "\n#import \"CYConst.h\"\n\n// 常量\nconst CGFloat CYPasswordInputViewHeight = (196 + 216);\nconst CGFloat CYPasswordViewTitleHeig"
  },
  {
    "path": "CYPasswordView/CYPasswordInputView.h",
    "chars": 259,
    "preview": "//\n//  CYPasswordInputView.h\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. Al"
  },
  {
    "path": "CYPasswordView/CYPasswordInputView.m",
    "chars": 6374,
    "preview": "//\n//  CYPasswordInputView.m\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. Al"
  },
  {
    "path": "CYPasswordView/CYPasswordView.h",
    "chars": 802,
    "preview": "//\n//  CYPasswordView.h\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All rig"
  },
  {
    "path": "CYPasswordView/CYPasswordView.m",
    "chars": 8025,
    "preview": "//\n//  CYPasswordView.m\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All rig"
  },
  {
    "path": "CYPasswordView/NSBundle+CYPasswordView.h",
    "chars": 497,
    "preview": "//\n//  NSBundle+NSBundle_CYPasswordView.h\n//  CYPasswordViewDemo\n//\n//  Created by apple on 2017/9/8.\n//  Copyright © 20"
  },
  {
    "path": "CYPasswordView/NSBundle+CYPasswordView.m",
    "chars": 2814,
    "preview": "//\n//  NSBundle+NSBundle_CYPasswordView.m\n//  CYPasswordViewDemo\n//\n//  Created by apple on 2017/9/8.\n//  Copyright © 20"
  },
  {
    "path": "CYPasswordView/UIDevice+Extension.h",
    "chars": 289,
    "preview": "//\n//  UIDevice+Extension.h\n//  CYPasswordViewDemo\n//\n//  Created by yong.chen on 2020/9/21.\n//  Copyright © 2020 zhssit"
  },
  {
    "path": "CYPasswordView/UIDevice+Extension.m",
    "chars": 401,
    "preview": "//\n//  UIDevice+Extension.m\n//  CYPasswordViewDemo\n//\n//  Created by yong.chen on 2020/9/21.\n//  Copyright © 2020 zhssit"
  },
  {
    "path": "CYPasswordView/UIView+Extension.h",
    "chars": 622,
    "preview": "//\n//  UIView+Extension.h\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All r"
  },
  {
    "path": "CYPasswordView/UIView+Extension.m",
    "chars": 1725,
    "preview": "//\n//  UIView+Extension.m\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All r"
  },
  {
    "path": "CYPasswordView.podspec",
    "chars": 1038,
    "preview": "#\n#  Be sure to run `pod spec lint CYPasswordView.podspec' to ensure this is a\n#  valid spec and to remove all comments "
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/AppDelegate.h",
    "chars": 278,
    "preview": "//\n//  AppDelegate.h\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All rights"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/AppDelegate.m",
    "chars": 2032,
    "preview": "//\n//  AppDelegate.m\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All rights"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 753,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/Assets.xcassets/arrow.imageset/Contents.json",
    "chars": 312,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n     "
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/Base.lproj/LaunchScreen.storyboard",
    "chars": 1662,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/Base.lproj/Main.storyboard",
    "chars": 26325,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/Info.plist",
    "chars": 1205,
    "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": "CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD+MJ.h",
    "chars": 571,
    "preview": "//\n//  MBProgressHUD+MJ.h\n//\n//  Created by MJ Lee on 13/4/18.\n//  Copyright (c) 2015年 itcast. All rights reserved.\n//\n\n"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD+MJ.m",
    "chars": 2379,
    "preview": "//\n//  MBProgressHUD+MJ.m\n//\n//  Created by MJ Lee on 13/4/18.\n//  Copyright (c) 2015年 itcast. All rights reserved.\n//\n\n"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD.h",
    "chars": 17101,
    "preview": "//\n//  MBProgressHUD.h\n//  Version 0.9\n//  Created by Matej Bukovinski on 2.4.09.\n//\n\n// This code is distributed under "
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/MBProgressHUD/MBProgressHUD.m",
    "chars": 33391,
    "preview": "//\n// MBProgressHUD.m\n// Version 0.9\n// Created by Matej Bukovinski on 2.4.09.\n//\n\n#import \"MBProgressHUD.h\"\n#import <tg"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/ViewController.h",
    "chars": 216,
    "preview": "//\n//  ViewController.h\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All rig"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/ViewController.m",
    "chars": 2607,
    "preview": "//\n//  ViewController.m\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All rig"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo/main.m",
    "chars": 335,
    "preview": "//\n//  main.m\n//  CYPasswordViewDemo\n//\n//  Created by cheny on 15/10/8.\n//  Copyright © 2015年 zhssit. All rights reserv"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo.xcodeproj/project.pbxproj",
    "chars": 18717,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 163,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:CYPasswordViewD"
  },
  {
    "path": "CYPasswordViewDemo/CYPasswordViewDemo.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": "LICENSE",
    "chars": 1073,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 cheny\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "README.md",
    "chars": 1038,
    "preview": "## CYPasswordView\n---\n`CYPasswordView`是一个模仿支付宝输入支付密码的密码框。\n### 一、说明\n---\n* `CYPasswordView`是一个简单且实用的输入密码框\n* 具体用法主要参考Demo程序"
  }
]

About this extraction

This page contains the full source code of the chernyog/CYPasswordView GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 34 files (134.0 KB), approximately 37.5k tokens, and a symbol index with 2 extracted functions, classes, methods, constants, and types. 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!