密码锁功能的实现
一个ios手势密码功能实现
ipad/iphone 都可以用
没有使用图片,里面可以通过view自己添加
keychain做的数据持久化,利用苹果官方KeychainItemWrapper类
keychain存储的数据不会因为删除app而清除记录,请调用-(void)clear
清除储存密码。
简单使用方式
下载后直接把 GesturePassword 下的GesturePassword文件丢到项目中去
在 TARGETS - Build Phases - "KeychainItemWrapper.m" - Compiler Flags (-fno-objc-arc)
在需要的地方直接可以调用ViewController
第一次的时候会两次验证密码
以后便会以这个密码进行确认
清空密码可以调用 - (void)clear
- (void)verify
验证手势密码在这里
- (void)reset
重置手势密码在这 (第一次回调用到这里进行第一次设置
保存于读取密码:
直接贴代码 KeychainItemWrapper *keychain=[[KeychainItemWrapper alloc] initWithIdentifier:@"xxxxxx" accessGroup:nil];//xxxx 自定义 保存 [keyWrapper setObject:@"myChainValues" forKey:(id)kSecAttrService]; [keyWrapper setObject:[usernameTextField text] forKey:(id)kSecAttrAccount];// 上面两行用来标识一个Item [keyWrapper setObject:[passwordTextField text] forKey:(id)kSecValueData]; 读取 [usernameTextField setText:[keyWrapper objectForKey:(id)kSecAttrAccount]]; [passwordTextField setText:[keyWrapper objectForKey:(id)kSecValueData]]; 另外需要引入Security.framework 和KeychainItemWrapper头文件(百度一下多得是)
下面简单的实现一下
一:我们先导入这个框架
二:新建一个手势密码的View分别在.h和.m文件中实现以下代码
GesturePasswordView.h
@protocol GesturePasswordDelegate <NSObject> - (void)forget; - (void)change; @end #import <UIKit/UIKit.h> #import "TentacleView.h" @interface GesturePasswordView : UIView<TouchBeginDelegate> @property (nonatomic,strong) TentacleView * tentacleView; @property (nonatomic,strong) UILabel * state; @property (nonatomic,assign) id<GesturePasswordDelegate> gesturePasswordDelegate; @property (nonatomic,strong) UIImageView * imgView; @property (nonatomic,strong) UIButton * forgetButton; @property (nonatomic,strong) UIButton * changeButton; @end
GesturePasswordView.m
#import "GesturePasswordView.h" #import "GesturePasswordButton.h" #import "TentacleView.h" @implementation GesturePasswordView { NSMutableArray * buttonArray; CGPoint lineStartPoint; CGPoint lineEndPoint; } @synthesize imgView; @synthesize forgetButton; @synthesize changeButton; @synthesize tentacleView; @synthesize state; @synthesize gesturePasswordDelegate; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code buttonArray = [[NSMutableArray alloc]initWithCapacity:]; UIView * view = [[UIView alloc]initWithFrame:CGRectMake(frame.size.width/-, frame.size.height/-, , )]; ; i<; i++) { NSInteger row = i/; NSInteger col = i%; // Button Frame NSInteger distance = /; NSInteger size = distance/1.5; NSInteger margin = size/; GesturePasswordButton * gesturePasswordButton = [[GesturePasswordButton alloc]initWithFrame:CGRectMake(col*distance+margin, row*distance, size, size)]; [gesturePasswordButton setTag:i]; [view addSubview:gesturePasswordButton]; [buttonArray addObject:gesturePasswordButton]; } frame.origin.y=; [self addSubview:view]; tentacleView = [[TentacleView alloc]initWithFrame:view.frame]; [tentacleView setButtonArray:buttonArray]; [tentacleView setTouchBeginDelegate:self]; [self addSubview:tentacleView]; state = [[UILabel alloc]initWithFrame:CGRectMake(frame.size.width/-, frame.size.height/-, , )]; [state setTextAlignment:NSTextAlignmentCenter]; [state setFont:[UIFont systemFontOfSize:.f]]; [self addSubview:state]; imgView = [[UIImageView alloc]initWithFrame:CGRectMake(frame.size.width/-, frame.size.width/-, , )]; [imgView setBackgroundColor:[UIColor whiteColor]]; [imgView.layer setCornerRadius:]; [imgView.layer setBorderColor:[UIColor grayColor].CGColor]; [imgView.layer setBorderWidth:]; [self addSubview:imgView]; forgetButton = [[UIButton alloc]initWithFrame:CGRectMake(frame.size.width/-, frame.size.height/+, , )]; [forgetButton.titleLabel setFont:[UIFont systemFontOfSize:]]; [forgetButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [forgetButton setTitle:@"忘记手势密码" forState:UIControlStateNormal]; [forgetButton addTarget:self action:@selector(forget) forControlEvents:UIControlEventTouchDown]; [self addSubview:forgetButton]; changeButton = [[UIButton alloc]initWithFrame:CGRectMake(frame.size.width/+, frame.size.height/+, , )]; [changeButton.titleLabel setFont:[UIFont systemFontOfSize:]]; [changeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [changeButton setTitle:@"修改手势密码" forState:UIControlStateNormal]; [changeButton addTarget:self action:@selector(change) forControlEvents:UIControlEventTouchDown]; [self addSubview:changeButton]; } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code CGContextRef context = UIGraphicsGetCurrentContext(); CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); CGFloat colors[] = { / / / 255.0, 1.00, / / / 255.0, 1.00, }; CGGradientRef gradient = CGGradientCreateWithColorComponents (rgb, colors, NULL, ])*)); CGColorSpaceRelease(rgb); CGContextDrawLinearGradient(context, gradient,CGPointMake (0.0,0.0) ,CGPointMake(0.0,self.frame.size.height), kCGGradientDrawsBeforeStartLocation); } - (void)gestureTouchBegin { [self.state setText:@""]; } -(void)forget{ [gesturePasswordDelegate forget]; } -(void)change{ [gesturePasswordDelegate change]; } @end
三:再自定义一个View用于实现界面的布局与处理
TentacleView.h
#import <UIKit/UIKit.h> @protocol ResetDelegate <NSObject> - (BOOL)resetPassword:(NSString *)result; @end @protocol VerificationDelegate <NSObject> - (BOOL)verification:(NSString *)result; @end @protocol TouchBeginDelegate <NSObject> - (void)gestureTouchBegin; @end @interface TentacleView : UIView @property (nonatomic,strong) NSArray * buttonArray; @property (nonatomic,assign) id<VerificationDelegate> rerificationDelegate; @property (nonatomic,assign) id<ResetDelegate> resetDelegate; @property (nonatomic,assign) id<TouchBeginDelegate> touchBeginDelegate; /* 1: Verify 2: Reset */ @property (nonatomic,assign) NSInteger style; - (void)enterArgin; @end
TentacleView.m
#import "TentacleView.h" #import "GesturePasswordButton.h" @implementation TentacleView { CGPoint lineStartPoint; CGPoint lineEndPoint; NSMutableArray * touchesArray; NSMutableArray * touchedArray; BOOL success; } @synthesize buttonArray; @synthesize rerificationDelegate; @synthesize resetDelegate; @synthesize touchBeginDelegate; @synthesize style; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code touchesArray = [[NSMutableArray alloc]initWithCapacity:]; touchedArray = [[NSMutableArray alloc]initWithCapacity:]; [self setBackgroundColor:[UIColor clearColor]]; [self setUserInteractionEnabled:YES]; success = ; } return self; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ CGPoint touchPoint; UITouch *touch = [touches anyObject]; [touchesArray removeAllObjects]; [touchedArray removeAllObjects]; [touchBeginDelegate gestureTouchBegin]; success=; if (touch) { touchPoint = [touch locationInView:self]; ; i<buttonArray.count; i++) { GesturePasswordButton * buttonTemp = ((GesturePasswordButton *)[buttonArray objectAtIndex:i]); [buttonTemp setSuccess:YES]; [buttonTemp setSelected:NO]; if (CGRectContainsPoint(buttonTemp.frame,touchPoint)) { CGRect frameTemp = buttonTemp.frame; CGPoint point = CGPointMake(frameTemp.origin.x+frameTemp.size.width/,frameTemp.origin.y+frameTemp.size.height/); NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%f",point.x],@"x",[NSString stringWithFormat:@"%f",point.y],@"y", nil]; [touchesArray addObject:dict]; lineStartPoint = touchPoint; } [buttonTemp setNeedsDisplay]; } [self setNeedsDisplay]; } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ CGPoint touchPoint; UITouch *touch = [touches anyObject]; if (touch) { touchPoint = [touch locationInView:self]; ; i<buttonArray.count; i++) { GesturePasswordButton * buttonTemp = ((GesturePasswordButton *)[buttonArray objectAtIndex:i]); if (CGRectContainsPoint(buttonTemp.frame,touchPoint)) { if ([touchedArray containsObject:[NSString stringWithFormat:@"num%d",i]]) { lineEndPoint = touchPoint; [self setNeedsDisplay]; return; } [touchedArray addObject:[NSString stringWithFormat:@"num%d",i]]; [buttonTemp setSelected:YES]; [buttonTemp setNeedsDisplay]; CGRect frameTemp = buttonTemp.frame; CGPoint point = CGPointMake(frameTemp.origin.x+frameTemp.size.width/,frameTemp.origin.y+frameTemp.size.height/); NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%f",point.x],@"x",[NSString stringWithFormat:@"%f",point.y],@"y",[NSString stringWithFormat:@"%d",i],@"num", nil]; [touchesArray addObject:dict]; break; } } lineEndPoint = touchPoint; [self setNeedsDisplay]; } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ NSMutableString * resultString=[NSMutableString string]; for ( NSDictionary * num in touchesArray ){ if(![num objectForKey:@"num"])break; [resultString appendString:[num objectForKey:@"num"]]; } ){ success = [rerificationDelegate verification:resultString]; } else { success = [resetDelegate resetPassword:resultString]; } ; i<touchesArray.count; i++) { NSInteger selection = [[[touchesArray objectAtIndex:i] objectForKey:@"num"]intValue]; GesturePasswordButton * buttonTemp = ((GesturePasswordButton *)[buttonArray objectAtIndex:selection]); [buttonTemp setSuccess:success]; [buttonTemp setNeedsDisplay]; } [self setNeedsDisplay]; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code // if (touchesArray.count<2)return; ; i<touchesArray.count; i++) { CGContextRef context = UIGraphicsGetCurrentContext(); if (![[touchesArray objectAtIndex:i] objectForKey:@"num"]) { //防止过快滑动产生垃圾数据 [touchesArray removeObjectAtIndex:i]; continue; } if (success) { CGContextSetRGBStrokeColor(context, /.f, /.f, /.f, 0.7);//线条颜色 } else { CGContextSetRGBStrokeColor(context, /.f, /.f, /.f, 0.7);//红色 } CGContextSetLineWidth(context,); CGContextMoveToPoint(context, [[[touchesArray objectAtIndex:i] objectForKey:@"x"] floatValue], [[[touchesArray objectAtIndex:i] objectForKey:@"y"] floatValue]); ) { CGContextAddLineToPoint(context, [[[touchesArray objectAtIndex:i+] objectForKey:] objectForKey:@"y"] floatValue]); } else{ if (success) { CGContextAddLineToPoint(context, lineEndPoint.x,lineEndPoint.y); } } CGContextStrokePath(context); } } - (void)enterArgin { [touchesArray removeAllObjects]; [touchedArray removeAllObjects]; ; i<buttonArray.count; i++) { GesturePasswordButton * buttonTemp = ((GesturePasswordButton *)[buttonArray objectAtIndex:i]); [buttonTemp setSelected:NO]; [buttonTemp setSuccess:YES]; [buttonTemp setNeedsDisplay]; } [self setNeedsDisplay]; }
四:自定义一个密码按钮的View
GesturePasswordButton.h
#import <UIKit/UIKit.h> @interface GesturePasswordButton : UIView @property (nonatomic,assign) BOOL selected; @property (nonatomic,assign) BOOL success; @end
GesturePasswordButton.m
#import "GesturePasswordButton.h" #define bounds self.bounds @implementation GesturePasswordButton @synthesize selected; @synthesize success; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code success=YES; [self setBackgroundColor:[UIColor clearColor]]; } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code CGContextRef context = UIGraphicsGetCurrentContext(); if (selected) { if (success) { CGContextSetRGBStrokeColor(context, /.f, /.f, /.f,);//线条颜色 CGContextSetRGBFillColor(context,/.f, /.f, /.f,); } else { CGContextSetRGBStrokeColor(context, /.f, /.f, /.f,);//线条颜色 CGContextSetRGBFillColor(context,/.f, /.f, /.f,); } CGRect frame = CGRectMake(bounds.size.width/-bounds.size.width/+, bounds.size.height/-bounds.size.height/, bounds.size.width/, bounds.size.height/); CGContextAddEllipseInRect(context,frame); CGContextFillPath(context); } else{ CGContextSetRGBStrokeColor(context, ,,,);//线条颜色 } CGContextSetLineWidth(context,); CGRect frame = CGRectMake(, , bounds.size.width-, bounds.size.height-); CGContextAddEllipseInRect(context,frame); CGContextStrokePath(context); if (success) { CGContextSetRGBFillColor(context,/.f, /.f, /.f,0.3); } else { CGContextSetRGBFillColor(context,/.f, /.f, /.f,0.3); } CGContextAddEllipseInRect(context,frame); if (selected) { CGContextFillPath(context); } } @end
五:前面的步骤都准备好了之后,我们就需要在控制器里面实现相应的代码
GesturePasswordController.h
#import <UIKit/UIKit.h> #import "TentacleView.h" #import "GesturePasswordView.h" @interface GesturePasswordController : UIViewController <VerificationDelegate,ResetDelegate,GesturePasswordDelegate> - (void)clear; - (BOOL)exist; @end
GesturePasswordController.m
#import <Security/Security.h> #import <CoreFoundation/CoreFoundation.h> #import "GesturePasswordController.h" #import "KeychainItemWrapper/KeychainItemWrapper.h" @interface GesturePasswordController () @property (nonatomic,strong) GesturePasswordView * gesturePasswordView; @end @implementation GesturePasswordController { NSString * previousString; NSString * password; } @synthesize gesturePasswordView; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. previousString = [NSString string]; KeychainItemWrapper * keychin = [[KeychainItemWrapper alloc]initWithIdentifier:@"Gesture" accessGroup:nil]; password = [keychin objectForKey:(__bridge id)kSecValueData]; if ([password isEqualToString:@""]) { [self reset]; } else { [self verify]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - 验证手势密码 - (void)verify{ gesturePasswordView = [[GesturePasswordView alloc]initWithFrame:[UIScreen mainScreen].bounds]; [gesturePasswordView.tentacleView setRerificationDelegate:self]; [gesturePasswordView.tentacleView setStyle:]; [gesturePasswordView setGesturePasswordDelegate:self]; [self.view addSubview:gesturePasswordView]; } #pragma mark - 重置手势密码 - (void)reset{ gesturePasswordView = [[GesturePasswordView alloc]initWithFrame:[UIScreen mainScreen].bounds]; [gesturePasswordView.tentacleView setResetDelegate:self]; [gesturePasswordView.tentacleView setStyle:]; // [gesturePasswordView.imgView setHidden:YES]; [gesturePasswordView.forgetButton setHidden:YES]; [gesturePasswordView.changeButton setHidden:YES]; [self.view addSubview:gesturePasswordView]; } #pragma mark - 判断是否已存在手势密码 - (BOOL)exist{ KeychainItemWrapper * keychin = [[KeychainItemWrapper alloc]initWithIdentifier:@"Gesture" accessGroup:nil]; password = [keychin objectForKey:(__bridge id)kSecValueData]; if ([password isEqualToString:@""])return NO; return YES; } #pragma mark - 清空记录 - (void)clear{ KeychainItemWrapper * keychin = [[KeychainItemWrapper alloc]initWithIdentifier:@"Gesture" accessGroup:nil]; [keychin resetKeychainItem]; } #pragma mark - 改变手势密码 - (void)change{ } #pragma mark - 忘记手势密码 - (void)forget{ } - (BOOL)verification:(NSString *)result{ if ([result isEqualToString:password]) { [gesturePasswordView.state setTextColor:[UIColor colorWithRed:/.f green:/.f blue:/.f alpha:]]; [gesturePasswordView.state setText:@"输入正确"]; //[self presentViewController:(UIViewController) animated:YES completion:nil]; return YES; } [gesturePasswordView.state setTextColor:[UIColor redColor]]; [gesturePasswordView.state setText:@"手势密码错误"]; return NO; } - (BOOL)resetPassword:(NSString *)result{ if ([previousString isEqualToString:@""]) { previousString=result; [gesturePasswordView.tentacleView enterArgin]; [gesturePasswordView.state setTextColor:[UIColor colorWithRed:/.f green:/.f blue:/.f alpha:]]; [gesturePasswordView.state setText:@"请验证输入密码"]; return YES; } else { if ([result isEqualToString:previousString]) { KeychainItemWrapper * keychin = [[KeychainItemWrapper alloc]initWithIdentifier:@"Gesture" accessGroup:nil]; [keychin setObject:@"<帐号>" forKey:(__bridge id)kSecAttrAccount]; [keychin setObject:result forKey:(__bridge id)kSecValueData]; //[self presentViewController:(UIViewController) animated:YES completion:nil]; [gesturePasswordView.state setTextColor:[UIColor colorWithRed:/.f green:/.f blue:/.f alpha:]]; [gesturePasswordView.state setText:@"已保存手势密码"]; return YES; } else{ previousString =@""; [gesturePasswordView.state setTextColor:[UIColor redColor]]; [gesturePasswordView.state setText:@"两次密码不一致,请重新输入"]; return NO; } } } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */
六:最终运行效果如下