iOS手勢密碼開發(fā)

前序

最近公司APP要做改版,其中要使用手勢密碼鎖型宙,所以提前寫了一個小Demo練練手嘱能,該Demo參考了DBGuestureLock吝梅。這里將詳細闡述代碼細節(jié),希望可以幫助到需要幫助的人惹骂。

相關(guān)界面GIF

Gesture.gif

代碼實現(xiàn)

一苏携、創(chuàng)建相關(guān)類

  • GesturePasswordButton
    該類主要是表示手勢密碼中的圓點
  • GesturePasswordView
    該類是手勢密碼View
  • GesturePasswordViewController
    該類是用于使用GesturePasswordView

二、繪制界面

從GIF圖可以看出对粪,手勢密碼一共有三種狀態(tài)(正常右冻、選擇、不正確)著拭,因此現(xiàn)在GesturePasswordView.h文件中創(chuàng)建一個枚舉類型

typedef NS_ENUM(NSInteger, GesturePasswordButtonState) {
    GesturePasswordButtonStateNormal = 0,
    GesturePasswordButtonStateSelected,
    GesturePasswordButtonStateIncorrect,
};

根據(jù)Button的形狀纱扭,可以在GesturePasswordView.h中定義以下屬性(之所以寫在GesturePasswordView.h中是為了根據(jù)不同的狀態(tài)改變button的樣式)

@property (nonatomic, assign)CGFloat strokeWidth; //圓弧的寬度
@property (nonatomic, assign)CGFloat circleRadius; //半徑
@property (nonatomic, assign)CGFloat centerPointRadius; //中心圓半徑
@property (nonatomic, assign)CGFloat lineWidth; //連接線寬度
@property (nonatomic, strong)UIColor *strokeColor; //圓弧的填充顏色
@property (nonatomic, strong)UIColor *fillColor; //除中心圓點外 其他部分的填充色
@property (nonatomic, strong)UIColor *centerPointColor; //中心圓點的顏色
@property (nonatomic, strong)UIColor *lineColor; //線條填充顏色
@property (nonatomic, assign)BOOL showCenterPoint; //是否顯示中心圓
@property (nonatomic, assign)BOOL fillCenterPoint; //是否填充中心圓

在GesturePasswordView.m文件中定義以下屬性,用于后面的代碼編寫茫死。(GesturePasswordStatus枚舉類型將會在后面寫出)

@property (nonatomic, strong) NSMutableArray *selectorAry;//存儲已經(jīng)選擇的按鈕
@property (nonatomic, assign)CGPoint currentPoint;//當(dāng)前處于哪個按鈕范圍內(nèi)
@property (nonatomic, assign)GesturePasswordStatus status;//當(dāng)前控件器所處狀態(tài)(設(shè)置跪但、重新設(shè)置、登錄)
@property (nonatomic, assign)NSInteger inputNum;//輸入的次數(shù)
@property (nonatomic, assign)NSInteger resetInputNum;//重置密碼時驗證舊密碼 輸入的次數(shù)
@property (nonatomic, strong)NSString *firstPassword;//表示設(shè)置密碼時 第一次輸入的手勢密碼

在GesturePasswordView.m文件中寫一個方法來改變button當(dāng)前的屬性值

- (void)setPropertiesByState:(GesturePasswordButtonState)buttonState{
    switch (buttonState) {
        case GesturePasswordButtonStateNormal:
            self.fillCenterPoint = YES;
            self.showCenterPoint = YES;
            self.strokeWidth = 1.f;
            self.centerPointRadius = 10.f;
            self.lineWidth = 2.f;
            self.lineColor = [UIColor whiteColor];
            self.fillColor = [UIColor whiteColor];
            self.strokeColor = [UIColor whiteColor];
            self.centerPointColor = [UIColor grayColor];
            break;
        case GesturePasswordButtonStateSelected:
            self.fillCenterPoint = YES;
            self.showCenterPoint = YES;
            self.strokeWidth = 1.f;
            self.centerPointRadius = 10.f;
            self.lineWidth = 2.f;
            self.lineColor = [UIColor greenColor];
            self.fillColor = RGBA(127, 255, 212, 1);
            self.strokeColor = RGBA(127, 255, 212, 1);
            self.centerPointColor = [UIColor greenColor];
            break;
        case GesturePasswordButtonStateIncorrect:
            self.fillCenterPoint = YES;
            self.showCenterPoint = YES;
            self.strokeWidth = 1.f;
            self.centerPointRadius = 10.f;
            self.lineWidth = 2.f;
            self.lineColor = [UIColor orangeColor];
            self.fillColor = RGBA(255, 245, 238, 1);
            self.strokeColor = RGBA(255, 245, 238, 1);
            self.centerPointColor = [UIColor orangeColor];
            break;
        default:
            break;
    }
}

在GesturePasswordView.m文件中使用initWithFrame:(CGRect)frame方法繪制手勢圖,這里GesturePasswordView的大小以(320峦萎,320)為基準(zhǔn)屡久。

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.selectorAry = [[NSMutableArray alloc] init];
        [self setPropertiesByState:GesturePasswordButtonStateNormal];
        NSInteger distance = 320/3;
        NSInteger size = distance/1.5;
        NSInteger margin = size/4;
        float ins = (SCREEN_WIDTH-320)/2;
        self.circleRadius = size/2;
        for (int i = 0; i < 9; i++) {
            NSInteger row = i/3;
            NSInteger col = i%3;
            GesturePasswordButton *gesturePasswordButton = [[GesturePasswordButton alloc] initWithFrame:CGRectMake(ins+col*distance+margin, row*distance+margin, size, size)];
            [gesturePasswordButton setTag:i+1];
            [self addSubview:gesturePasswordButton];
        }
        [self setBackgroundColor:[UIColor clearColor]];
    }
    return self;
}

在GesturePasswordButton.m文件中重新initWithFrame:(CGRect)frame方法。

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.userInteractionEnabled = NO;
    }
    return self;
}

在GesturePasswordButton.m文件中重新- (void)drawRect:(CGRect)rect方法爱榔。

  • 獲取到父視圖(GesturePasswordView)被环,使用其相關(guān)描述button的屬性。
    __weak GesturePasswordView *gesView = nil;
    if ([self.superview isKindOfClass:[GesturePasswordView class]]) {
        gesView = (GesturePasswordView *)self.superview;
    }
  • 繪制外圈大圓
    CGFloat radius = gesView.circleRadius - gesView.strokeWidth;
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, gesView.strokeWidth);
    CGPoint centerPoint = CGPointMake(rect.size.width/2, rect.size.height/2);
    CGFloat startAngle = -((CGFloat)M_PI/2);
    CGFloat endAngle = ((2 * (CGFloat)M_PI) + startAngle);
    [gesView.strokeColor setStroke];
    CGContextAddArc(context, centerPoint.x, centerPoint.y, radius+gesView.strokeWidth/2, startAngle, endAngle, 0);
    CGContextStrokePath(context);//CGContextStrokePath來描線,即形狀 
  • 根據(jù)是否顯示中心點繪制形狀
if (gesView.showCenterPoint) {
        [gesView.fillColor set];//同時設(shè)置填充和邊框色
        CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, startAngle, endAngle, 0);
        CGContextFillPath(context);//CGContextFillPath來填充形狀內(nèi)的顏色
        if (gesView.fillCenterPoint) {
            [gesView.centerPointColor set];//同時設(shè)置填充和邊框色
        }else{
            [gesView.centerPointColor setStroke];//設(shè)置邊框色
        }
        CGContextAddArc(context, centerPoint.x, centerPoint.y, gesView.centerPointRadius, startAngle, endAngle, 0);
        if (gesView.fillCenterPoint) {
            CGContextFillPath(context);//CGContextFillPath來填充形狀內(nèi)的顏色
        }else{
            CGContextStrokePath(context);//CGContextStrokePath來描線,即形狀 
        }
    }

整體drawRect方法如下:

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    __weak GesturePasswordView *gesView = nil;
    if ([self.superview isKindOfClass:[GesturePasswordView class]]) {
        gesView = (GesturePasswordView *)self.superview;
    }
    CGFloat width = rect.size.height > rect.size.width ? rect.size.width : rect.size.height;
    CGFloat radius = (width - 2*gesView.strokeWidth)/2;
    if (radius > (gesView.circleRadius - gesView.strokeWidth)) {
        radius = gesView.circleRadius - gesView.strokeWidth;
    }
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, gesView.strokeWidth);
    CGPoint centerPoint = CGPointMake(rect.size.width/2, rect.size.height/2);
    CGFloat startAngle = -((CGFloat)M_PI/2);
    CGFloat endAngle = ((2 * (CGFloat)M_PI) + startAngle);
    [gesView.strokeColor setStroke];
    CGContextAddArc(context, centerPoint.x, centerPoint.y, radius+gesView.strokeWidth/2, startAngle, endAngle, 0);
    CGContextStrokePath(context);//CGContextStrokePath來描線,即形狀 
    
    if (gesView.showCenterPoint) {
        [gesView.fillColor set];//同時設(shè)置填充和邊框色
        CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, startAngle, endAngle, 0);
        CGContextFillPath(context);//CGContextFillPath來填充形狀內(nèi)的顏色
        
        if (gesView.fillCenterPoint) {
            [gesView.centerPointColor set];//同時設(shè)置填充和邊框色
        }else{
            [gesView.centerPointColor setStroke];//設(shè)置邊框色
        }
        
        CGContextAddArc(context, centerPoint.x, centerPoint.y, gesView.centerPointRadius, startAngle, endAngle, 0);
        if (gesView.fillCenterPoint) {
            CGContextFillPath(context);//CGContextFillPath來填充形狀內(nèi)的顏色
        }else{
            CGContextStrokePath(context);//CGContextStrokePath來描線,即形狀 
        }
    }
}

這樣的話只需要在GesturePasswordViewController中加載GesturePasswordView就可以顯示出手勢密碼的界面详幽。

三筛欢、實現(xiàn)三種手勢狀態(tài)

為了實現(xiàn)手勢的三種狀態(tài),我們需要獲取到用戶的觸摸動作唇聘,這里我們將使用UIResponder類版姑,UIResponder類是專門用來響應(yīng)用戶的操作處理各種事件的,所以我們需要在GesturePasswordView.m實現(xiàn)touchesBegan迟郎、touchesMoved剥险、touchesEnded方法。

  • touchesBegan方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];//獲取觸摸點在view中的位置
    self.currentPoint = point;
    for (GesturePasswordButton *btn in self.subviews) {
        if (CGRectContainsPoint(btn.frame, point)) {//判斷觸摸點是否在當(dāng)前btn的范圍之內(nèi)
            [btn setSelected:YES];
            if (![self.selectorAry containsObject:btn]) {
                [self.selectorAry addObject:btn];
                [self setPropertiesByState:GesturePasswordButtonStateSelected];//改變該btn的狀態(tài)
            }
        }
    }
    [self setNeedsDisplay];//重繪view來畫線
}
  • touchesMoved方法
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    self.currentPoint = point;
    for (GesturePasswordButton *btn in self.subviews) {
        if (CGRectContainsPoint(btn.frame, point)) {
            [btn setSelected:YES];
            if (![self.selectorAry containsObject:btn]) {
                [self.selectorAry addObject:btn];
                [self setPropertiesByState:GesturePasswordButtonStateSelected];
            }
        }
    }
    [self setNeedsDisplay];
}
  • touchesEnded方法
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    GesturePasswordButton *btn = [self.selectorAry lastObject];
    [self setCurrentPoint:btn.center];
    [self setNeedsDisplay];
}
  • 調(diào)用drawRect方法 重繪view
- (void)drawRect:(CGRect)rect{
    [super drawRect:rect];
    if ([self.selectorAry count] == 0) {
        return;
    }
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path setLineWidth:self.lineWidth];
    [self.lineColor set];
    [path setLineJoinStyle:kCGLineJoinRound];
    [path setLineCapStyle:kCGLineCapRound];
    for (NSInteger i = 0; i < self.selectorAry.count; i ++) {
        GesturePasswordButton *btn = self.selectorAry[i];
        if (i == 0) {
            [path moveToPoint:[btn center]];
        }else{
            [path addLineToPoint:[btn center]];
        }
        [btn setNeedsDisplay];
    }
    [path addLineToPoint:self.currentPoint];
    [path stroke];
}
  • 為了實現(xiàn)當(dāng)用戶輸入錯誤后宪肖,不正確狀態(tài)顯示0.5秒后恢復(fù)為正常狀態(tài)表制,需要在上面實現(xiàn)的setPropertiesByState方法中加入如下代碼,另外實現(xiàn)resetButtons和lockState方法
case GesturePasswordButtonStateNormal:
            [self setUserInteractionEnabled:YES];\\設(shè)置當(dāng)前用戶可以進行觸摸操作
            [self resetButtons];
            self.fillCenterPoint = YES;
case GesturePasswordButtonStateIncorrect:
            [self setUserInteractionEnabled:NO];\\設(shè)置當(dāng)前用戶不可進行觸摸操作
            self.fillCenterPoint = YES;
            self.showCenterPoint = YES;
            self.strokeWidth = 1.f;
            self.centerPointRadius = 10.f;
            self.lineWidth = 2.f;
            self.lineColor = [UIColor orangeColor];
            self.fillColor = RGBA(255, 245, 238, 1);
            self.strokeColor = RGBA(255, 245, 238, 1);
            self.centerPointColor = [UIColor orangeColor];
            [self performSelector:@selector(lockState:) withObject:[NSArray arrayWithObject:[NSNumber numberWithInteger:GesturePasswordButtonStateNormal]] afterDelay:0.5f];\\0.5秒后執(zhí)行l(wèi)ockState方法
\\重置selectorAry數(shù)組
- (void)resetButtons {
    for (NSInteger i=0; i<[self.selectorAry count]; i++) {
        GesturePasswordButton *button = self.selectorAry[i];
        [button setSelected:NO];
    }
    [self.selectorAry removeAllObjects];
    [self setNeedsDisplay];
}
\\切換btn狀態(tài)
- (void)lockState:(NSArray *)states {
    NSNumber *stateNumber = [states objectAtIndex:0];
    [self setPropertiesByState:[stateNumber integerValue]];
}

四控乾、調(diào)用GesturePasswordView

現(xiàn)在我們要明確一下這個GesturePasswordView主要用于手勢登錄么介、設(shè)置手勢密碼纫事、重置手勢密碼這三種情況底靠。那么在GesturePasswordViewController.h中可以創(chuàng)建一個枚舉類型。

typedef NS_ENUM(NSInteger, GesturePasswordStatus) {
    GesturePasswordStatusSet           = 0,\\設(shè)置
    GesturePasswordStatusReset         = 1,\\重置
    GesturePasswordStatusLogin         = 2,\\登錄
};

登錄雁社、設(shè)置、重置三種狀態(tài)下的流程圖

流程圖.png

根據(jù)流程圖我們可以在GesturePasswordView.h中創(chuàng)建六種類型的Block方法

@property (nonatomic, copy) void(^verificationPassword)();//驗證舊密碼正確
@property (nonatomic, copy) void(^verificationError)();//驗證舊密碼錯誤
@property (nonatomic, copy) void(^onPasswordSet)();//第一次輸入密碼
@property (nonatomic, copy) void(^onGetCorrectPswd)();//第二次輸入密碼且和第一次一樣
@property (nonatomic, copy) void(^onGetIncorrectPswd)();//第二次輸入密碼且和第一次不一樣
@property (nonatomic, copy) void(^errorInput)();//手勢密碼小于四位數(shù)

根據(jù)三種狀態(tài)我們可以在GesturePasswordView.h中創(chuàng)建三種初始化方法

+(instancetype)status:(GesturePasswordStatus)status frame:(CGRect)frame onGetCorrectPswd:(void (^)())GetCorrectPswd onGetIncorrectPswd:(void (^)())GetIncorrectPswd errorInput:(void (^)())errorInput;//用于登錄

+(instancetype)status:(GesturePasswordStatus)status frame:(CGRect)frame  onPasswordSet:(void (^)())onPasswordSet onGetCorrectPswd:(void (^)())GetCorrectPswd onGetIncorrectPswd:(void (^)())GetIncorrectPswd errorInput:(void (^)())errorInput;//用于設(shè)置

+(instancetype)status:(GesturePasswordStatus)status frame:(CGRect)frame verificationPassword:(void (^)())verificationPassword verificationError:(void (^)())verificationError onPasswordSet:(void (^)())onPasswordSet onGetCorrectPswd:(void (^)())GetCorrectPswd onGetIncorrectPswd:(void (^)())GetIncorrectPswd errorInput:(void (^)())errorInput;//用于重置

在GesturePasswordView.m中實現(xiàn)這三種方法

+(instancetype)status:(GesturePasswordStatus)status frame:(CGRect)frame onGetCorrectPswd:(void (^)())GetCorrectPswd onGetIncorrectPswd:(void (^)())GetIncorrectPswd errorInput:(void (^)())errorInput
{
    return [self status:status frame:frame onPasswordSet:nil onGetCorrectPswd:GetCorrectPswd onGetIncorrectPswd:GetIncorrectPswd errorInput:errorInput];
}

+(instancetype)status:(GesturePasswordStatus)status frame:(CGRect)frame  onPasswordSet:(void (^)())onPasswordSet onGetCorrectPswd:(void (^)())GetCorrectPswd onGetIncorrectPswd:(void (^)())GetIncorrectPswd errorInput:(void (^)())errorInput
{
    return [self status:status frame:frame verificationPassword:nil verificationError:nil onPasswordSet:onPasswordSet onGetCorrectPswd:GetCorrectPswd onGetIncorrectPswd:GetIncorrectPswd errorInput:errorInput];
}

+(instancetype)status:(GesturePasswordStatus)status frame:(CGRect)frame verificationPassword:(void (^)())verificationPassword verificationError:(void (^)())verificationError onPasswordSet:(void (^)())onPasswordSet onGetCorrectPswd:(void (^)())GetCorrectPswd onGetIncorrectPswd:(void (^)())GetIncorrectPswd errorInput:(void (^)())errorInput
{
    GesturePasswordView *gesView = [[GesturePasswordView alloc] initWithFrame:frame];
    gesView.status = status;
    gesView.verificationPassword = verificationPassword;
    gesView.verificationError = verificationError;
    gesView.onPasswordSet = onPasswordSet;
    gesView.onGetCorrectPswd = GetCorrectPswd;
    gesView.onGetIncorrectPswd = GetIncorrectPswd;
    gesView.errorInput = errorInput;
    return gesView;
}

在touchesEnded方法中久脯,我們可以根據(jù)當(dāng)前出入哪種狀態(tài)做出相應(yīng)的處理蒜绽,所以touchesEnded方法應(yīng)該是這樣的:

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    if (self.selectorAry.count < 4) {
        self.errorInput();
        [self setPropertiesByState:GesturePasswordButtonStateNormal];
    }else if (self.status == GesturePasswordStatusSet) {
        [self setPasswordBlock];
    }else if(self.status == GesturePasswordStatusReset){
        NSString *password = [self getPassword];
        NSString *inputPassword  = [[NSString alloc] init];
        if (self.resetInputNum == 0) {
            for (GesturePasswordButton *btn in self.selectorAry) {
                inputPassword = [inputPassword stringByAppendingFormat:@"%@",@(btn.tag)];
            }
            if ([inputPassword isEqualToString:password]) {
                self.verificationPassword();
                self.resetInputNum += 1;
                [self performSelector:@selector(lockState:) withObject:[NSArray arrayWithObject:[NSNumber numberWithInteger:GesturePasswordButtonStateNormal]] afterDelay:0.3f];
            }else{
                self.verificationError();
                [self setPropertiesByState:GesturePasswordButtonStateIncorrect];
            }
        }else if(self.resetInputNum == 1){
            [self setPasswordBlock];
        }
    }else if(self.status == GesturePasswordStatusLogin){
        NSString *password = [self getPassword];
        NSString *inputPassword  = [[NSString alloc] init];
        for (GesturePasswordButton *btn in self.selectorAry) {
            inputPassword = [inputPassword stringByAppendingFormat:@"%@",@(btn.tag)];
        }
        if ([inputPassword isEqualToString:password]) {
            self.onGetCorrectPswd();
            [self setPropertiesByState:GesturePasswordButtonStateNormal];
        }else{
            self.onGetIncorrectPswd();
            [self setPropertiesByState:GesturePasswordButtonStateIncorrect];
        }
    }
    GesturePasswordButton *btn = [self.selectorAry lastObject];
    [self setCurrentPoint:btn.center];
    [self setNeedsDisplay];
}
- (void)setPasswordBlock
{
    if (self.inputNum == 0) {
        self.firstPassword = [[NSString alloc] init];
        for (GesturePasswordButton *btn in self.selectorAry) {
            self.firstPassword = [self.firstPassword stringByAppendingFormat:@"%@",@(btn.tag)];
        }
        self.onPasswordSet();
        self.inputNum += 1;
        [self performSelector:@selector(lockState:) withObject:[NSArray arrayWithObject:[NSNumber numberWithInteger:GesturePasswordButtonStateNormal]] afterDelay:0.3f];
    }else{
        NSString *secondPassword = [[NSString alloc] init];
        for (GesturePasswordButton *btn in self.selectorAry) {
            secondPassword = [secondPassword stringByAppendingFormat:@"%@",@(btn.tag)];
        }
        if ([self.firstPassword isEqualToString:secondPassword]) {
            [self savePassWord:secondPassword];
            self.onGetCorrectPswd();
            [self performSelector:@selector(lockState:) withObject:[NSArray arrayWithObject:[NSNumber numberWithInteger:GesturePasswordButtonStateNormal]] afterDelay:0.3f];
        }else{
            self.onGetIncorrectPswd();
            [self setPropertiesByState:GesturePasswordButtonStateIncorrect];
            self.inputNum -= 1;
        }
    }
}

存取密碼的方法

- (void)savePassWord:(NSString *)password
{
    NSUserDefaults *userdefault = [NSUserDefaults standardUserDefaults];
    [userdefault setObject:@{@"password":password} forKey:GESTUREPASSWORD];
    [userdefault synchronize];
}

- (NSString *)getPassword
{
    NSDictionary *dic = [[NSUserDefaults standardUserDefaults] objectForKey:GESTUREPASSWORD];
    return [dic objectForKey:@"password"];
}

在GesturePasswordViewController.h這樣調(diào)用

if (self.status == GesturePasswordStatusSet) {
        self.infoLabel.text = @"請設(shè)置手勢密碼";
        GesturePasswordView *view = [GesturePasswordView status:GesturePasswordStatusSet frame:CGRectMake(0, 200,  SCREEN_WIDTH, 400) onPasswordSet:^() {
            self.infoLabel.text = @"請重新輸入剛才設(shè)置的手勢密碼";
        } onGetCorrectPswd:^ {
            self.infoLabel.text = @"設(shè)置成功";
            [weakSelf setGesturePasswordSwitchOpen];
        } onGetIncorrectPswd:^ {
            self.infoLabel.text = @"與上一次輸入不一致,請重新設(shè)置";
        } errorInput:^{
            self.infoLabel.text = @"請至少連接4個點";
        }];
        [self.view addSubview:view];
    }else if (self.status == GesturePasswordStatusReset){
        self.infoLabel.text = @"請驗證舊密碼";
        GesturePasswordView *view = [GesturePasswordView status:GesturePasswordStatusReset frame:CGRectMake(0, 200,  SCREEN_WIDTH, 400) verificationPassword:^{
            self.infoLabel.text = @"請輸入新的手勢密碼";
        } verificationError:^{
            self.infoLabel.text = @"舊密碼驗證錯誤";
        }  onPasswordSet:^ {
            self.infoLabel.text = @"請重新輸入剛才設(shè)置的手勢密碼";
        } onGetCorrectPswd:^ {
            self.infoLabel.text = @"設(shè)置成功";
            [weakSelf setGesturePasswordSwitchOpen];
        } onGetIncorrectPswd:^ {
            self.infoLabel.text = @"與上一次輸入不一致桶现,請重新設(shè)置";
        } errorInput:^{
            self.infoLabel.text = @"請至少連接4個點";
        }];
        [self.view addSubview:view];
    }else if (self.status == GesturePasswordStatusLogin){
        self.infoLabel.text = @"請輸入手勢密碼";
        GesturePasswordView *view = [GesturePasswordView status:GesturePasswordStatusLogin frame:CGRectMake(0, 200,  SCREEN_WIDTH, 400) onGetCorrectPswd:^ {
            self.infoLabel.text = @"解鎖成功";
            [self loginSuccess];
        } onGetIncorrectPswd:^ {
            self.infoLabel.text = @"密碼錯誤,請重新輸入";
        } errorInput:^{
            self.infoLabel.text = @"請至少連接4個點";
        }];
        [self.view addSubview:view];
    }

結(jié)束語

整個思路大致就是這樣的鼎姊,主體實現(xiàn)的代碼已經(jīng)在文章中寫出來了骡和,當(dāng)然還有手勢密碼鎖的開啟與關(guān)閉等一些細節(jié)代碼沒有寫出,如果需要完整代碼的可以前往github下載Demo相寇。如果有什么不對的地方慰于,希望大家可以及時的指出,謝謝;缴馈F旁!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末佳励,一起剝皮案震驚了整個濱河市休里,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赃承,老刑警劉巖妙黍,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瞧剖,居然都是意外死亡拭嫁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門抓于,熙熙樓的掌柜王于貴愁眉苦臉地迎上來做粤,“玉大人,你說我怎么就攤上這事捉撮∨缕罚” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵呕缭,是天一觀的道長堵泽。 經(jīng)常有香客問我,道長恢总,這世上最難降的妖魔是什么迎罗? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮片仿,結(jié)果婚禮上纹安,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好厢岂,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布光督。 她就那樣靜靜地躺著,像睡著了一般塔粒。 火紅的嫁衣襯著肌膚如雪结借。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天卒茬,我揣著相機與錄音船老,去河邊找鬼。 笑死圃酵,一個胖子當(dāng)著我的面吹牛柳畔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播郭赐,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼薪韩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了捌锭?” 一聲冷哼從身側(cè)響起俘陷,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎观谦,沒想到半個月后岭洲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡坎匿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年盾剩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片替蔬。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡告私,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出承桥,到底是詐尸還是另有隱情驻粟,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布凶异,位于F島的核電站蜀撑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏剩彬。R本人自食惡果不足惜酷麦,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喉恋。 院中可真熱鬧沃饶,春花似錦母廷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至馆揉,卻和暖如春业舍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背升酣。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工勤讽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拗踢。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像向臀,于是被迫代替她去往敵國和親巢墅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容