iOS开发——高级技术&密码锁功能的实现
密码锁功能的实现
一个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. } */
六:最终运行效果如下
iOS开发——高级技术&密码锁功能的实现的更多相关文章
- iOS开发——高级技术&广告功能的实现
广告功能的实现 iPhone/iPad的程序,即使是Free的版本,也可以通过广告给我们带来收入.前提是你的程序足够吸引人,有足够的下载量.这里,我将介绍一下程序中集成广告的方法.主要有两种广告iAd ...
- iOS开发——高级技术&通讯录功能的实现
通讯录功能的实现 iOS 提供了对通讯录操作的组建,其中一个是直接操作通讯录,另一个是调用通讯录的 UI 组建.实现方法如下: 添加AddressBook.framework到工程中. 代码实现: 1 ...
- iOS开发——高级技术&支付宝功能的实现
支付宝功能的实现 现在不少app内都集成了支付宝功能 使用支付宝进行一个完整的支付功能,大致有以下步骤: 1>先与支付宝签约,获得商户ID(partner)和账号ID(seller) (这个 ...
- iOS开发——高级技术&摇一摇功能的实现
摇一摇功能的实现 在AppStore中多样化功能越来越多的被使用了,所以今天就开始介绍一些iOS开发的比较实用,但是我们接触的比较少的功能,我们先从摇一摇功能开始 在 UIResponder中存在这么 ...
- iOS开发——高级技术OC篇&运行时(Runtime)机制
运行时(Runtime)机制 本文将会以笔者个人的小小研究为例总结一下关于iOS开发中运行时的使用和常用方法的介绍,关于跟多运行时相关技术请查看笔者之前写的运行时高级用法及相关语法或者查看响应官方文档 ...
- iOS开发——高级技术精选OC篇&Runtime之字典转模型实战
Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...
- iOS开发——高级技术&广告服务
广告服务 上 面也提到做iOS开发另一收益来源就是广告,在iOS上有很多广告服务可以集成,使用比较多的就是苹果的iAd.谷歌的Admob,下面简单演示一下如何 使用iAd来集成广告.使用iAd集成广告 ...
- iOS开发——高级技术&内购服务
内购服务 大家都知道做iOS开发本身的收入有三种来源:出售应用.内购和广告.国内用户通常很少直接 购买应用,因此对于开发者而言(特别是个人开发者),内购和广告收入就成了主要的收入来源.内购营销模式,通 ...
- iOS开发——高级技术&签名机制
签名机制 最近看了objc.io上第17期中的文章 <Inside Code Signing> 对应的中文翻译版 <代码签名探析> ,受益颇深,对iOS代码签名机制有了进一步的 ...
随机推荐
- SharePoint 2010 master page 控件介绍(4):隐藏placeholder
转:http://blog.csdn.net/lgm97/article/details/6409225 <!-- form digest 安全控件用来进行form的安全校验--> &l ...
- DbHelper and OracleHelper
1 连接Sql Server的ConnectionString: Data Source=.;Initial Catalog=ViewVideo;User ID=sa;Password=XXXXXX; ...
- [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]PrI.6.1
Given a basis $U=(u_1,\cdots,u_n)$ not necessarily orthonormal, in $\scrH$, how would you compute th ...
- 解决:Eclipse导入工程后全是错误,连基本类型都不识别
当初在大学没时间完成作业时,总是喜欢网上搜一个或者拷贝同学的一个工程过来,导入到Eclipse中却全是红叉,连基本类型都不识别. 当时就纳闷了,难道是天要亡我之心不死?后来慢慢了解了,其实是导入的工程 ...
- input子系统 KeyPad-Touch上报数据格式与机制
-----------------------------------------------------------------------本文系本站原创,欢迎转载!转载请注明出处:http://b ...
- 6.2 CUDA streams
stream是什么 nivdia给出的解释是:A sequence of operations that execute in issue-order on the GPU. 可以理解成在GPU上执 ...
- 自编译安装nginx
1. 下载nginx,并解压 http://nginx.org/ 2. 下载health check模块 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 1 ...
- Sitecore Digital Marketing System, Part 1: Creating personalized, custom content for site visitors(自定义SiteCore中的 Item的Personalize的Condition) -摘自网络
Sitecore’s Digital Marketing System (DMS) can help you personalize the content your site displays to ...
- Java中使用ThreadPoolExecutor并行执行独立的单线程任务
Java SE 5.0中引入了任务执行框架,这是简化多线程程序设计开发的一大进步.使用这个框架可以方便地管理任务:管理任务的生命周期以及执行策略. 在这篇文章中,我们通过一个简单的例子来展现这个框架所 ...
- [OC Foundation框架 - 20] 统计代码行数
注意: 1.变量名和函数名不要混淆调用 2.不要对文件夹进行文件的操作,没有权限 3.递归调用注意初始化变量 // // main.m // CodeLineCount // // Created ...