iOS realizes gesture password function

  • 2021-11-13 02:56:58
  • OfStack

Gesture password implementation

Gesture password 1 is often used in financial projects, which are security-related businesses. Specific implementation of the following ideas, I divided it into view layer and logic layer. I have merged the data layer into the view layer, preferably adding the data layer to handle encrypted passwords and password storage

view layer

view layer mainly deals with (9 buttons) touchesBegan, touchesMoved, touchesEnded, drawing lines between points, sliding animation lines with fingers, and drawing lines is mainly redrawn in drawRect. It is mentioned that setNeedsDisplay must not be forgotten here. Also record the passing button btnsArray (array of buttons), which can be mapped with relevant specific values, or directly set btn tag, and add a callback to complete painting. Provided to the logical layer for processing.

Logical layer

Used to handle the business after the interaction is completed, including (request interface, exception logic display, etc.)
The specific demo point here

Specific code:
view.h


//
// YHGesturePasswordView.h
//  Gesture code 
//
// Created by mrlee on 2017/3/5.
// Copyright © 2017 Year  mrlee. All rights reserved.
//
typedef enum {
  GestureSetPassword, // Set gesture password 
  GestureResultPassword // Existing gesture password teaching 
} PasswordState;
// That sets the password 3 Species state 
typedef enum {
  FristPwd, // No. 1 1 Second set password 
  PwdNoValue, //2 Setting the password for the second time does not 1 To 
  SetPwdSuccess, // Password set successfully 
  Other
}SetPwdState;

#import <UIKit/UIKit.h>

@interface YHGesturePasswordView : UIView
/** btn Picture */
@property (nonatomic,strong)UIImage *btnImage;

/// Selected picture 
@property (nonatomic,strong)UIImage *btnSelectImage;

/// Scribe color 
@property (nonatomic,strong)UIColor *lineColor;

/**  Called when judging the result after the unlock gesture is completed block */
@property (nonatomic,copy)BOOL (^sendReaultData)(NSString *str);

// Set gesture password 
@property(nonatomic,copy)void(^setPwdBlock)(SetPwdState pwdState);


// init
-(instancetype)initWithFrame:(CGRect)frame WithState:(PasswordState)state;

@end

view.m


//
// YHGesturePasswordView.m
//  Gesture code 
//
// Created by mrlee on 2017/3/5.
// Copyright © 2017 Year  mrlee. All rights reserved.
//
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
#import "YHCustomButton.h"
#import "YHGesturePasswordView.h"
#import <CommonCrypto/CommonDigest.h>
@interface YHGesturePasswordView(){
  /**  Determine whether it is used for setting password or unlocking password */
  PasswordState Amode;
}
/**  All button sets */
@property (nonatomic,strong)NSMutableArray * allBtnsArray;

/**  All the fingers that pass when unlocking btn Set */
@property (nonatomic,strong)NSMutableArray * btnsArray;

/**  The current touch position of the finger */
@property (nonatomic,assign)CGPoint currentPoint;

@end

@implementation YHGesturePasswordView

-(instancetype)initWithFrame:(CGRect)frame WithState:(PasswordState)state{
  self = [super initWithFrame:frame];
  if (self) {
     self.backgroundColor = [UIColor clearColor];
    Amode = state;
    for (int i = 0; i<9; i++) {
      YHCustomButton *btn = [[YHCustomButton alloc]init];
      [btn setTag:i];
      btn.userInteractionEnabled = NO;
      if (self.lineColor == nil) {
        self.lineColor = [UIColor greenColor];
      }
      [self addSubview:btn];
    }

  }
  return self;
}
-(void)drawRect:(CGRect)rect{
  //  Every time this method is called, if the background color is default Cache will be generated. If there is no cache after setting the color, the cache needs to be cleared before drawing 
  CGContextRef ctx = UIGraphicsGetCurrentContext();
  CGContextClearRect(ctx, rect);// Empty context 
  for (int i = 0; i<self.btnsArray.count; i++) {
    UIButton *btn = self.btnsArray[i];
    if (i == 0) {
      CGContextMoveToPoint(ctx, btn.center.x, btn.center.y);
    }else{
      CGContextAddLineToPoint(ctx, btn.center.x, btn.center.y);
    }
  }
  if (!CGPointEqualToPoint(self.currentPoint, CGPointZero)) {// If the starting point is not CGPointZero Only then will you draw the line 
    CGContextAddLineToPoint(ctx, self.currentPoint.x, self.currentPoint.y);
  }

  CGContextSetLineWidth(ctx, 12);
  CGContextSetLineCap(ctx, kCGLineCapRound);
  CGContextSetLineJoin(ctx, kCGLineJoinRound);
  [self.lineColor set];
  CGContextStrokePath(ctx);

}
-(void)layoutSubviews{

   [self.allBtnsArray removeAllObjects];
  for (int index =0; index<self.subviews.count; index ++) {
    if ([self.subviews[index] isKindOfClass:[YHCustomButton class]]) {

      [self.allBtnsArray addObject:self.subviews[index]];
    }
  }
  // button  Draw 9 Palace lattice 
  [self drawUi];


}
#pragma mark Private method
-(void)drawUi{
  for (int index = 0; index<self.allBtnsArray.count; index ++) {
    // Get every btn
    UIButton *btn = self.subviews[index];

    // Settings frame
    CGFloat btnW = 74;
    CGFloat btnH = 74;
    CGFloat margin = (SCREEN_WIDTH - (btnW *3))/4;
    //x =  Spacing  +  Column number * (Spacing +btnW ) 
    CGFloat btnX = margin + (index % 3)*(margin + btnW);
    CGFloat btnY = margin + (index / 3)*(margin + btnH);

    btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
  }

}
// Set password 
-(SetPwdState)pwdValue:(NSString *)str{
  if ([[NSUserDefaults standardUserDefaults] objectForKey:@"pwdValue"] == nil) {
    // No. 1 1 Secondary setting 
    [[NSUserDefaults standardUserDefaults] setValue:str forKey:@"pwdValue"];
    return FristPwd;
  }
  if ([str isEqualToString: [[NSUserDefaults standardUserDefaults]objectForKey:@"pwdValue"]]) {
    // Setup succeeded 
    return SetPwdSuccess;
  }
  if (![str isEqualToString: [[NSUserDefaults standardUserDefaults]objectForKey:@"pwdValue"]]) {
    //2 Secondary setting does not 1 Sample 
    return PwdNoValue;
  }

  return Other;

}
// Empty 
-(void)clear{
  [self.btnsArray removeAllObjects];
  self.currentPoint = CGPointZero;
  [self setNeedsDisplay];
  self.lineColor = [UIColor greenColor];
  self.userInteractionEnabled = YES;
}
// Get the touched point 
-(CGPoint)getCurrentTouch:(NSSet<UITouch*> *)touches{
  UITouch *touch = [touches anyObject];
  CGPoint point = [touch locationInView:touch.view];
  return point;
}

-(UIButton *)getCurrentBtnWithPoint:(CGPoint) currentPoint{
  for (UIButton *btn in self.subviews) {
    if (CGRectContainsPoint(btn.frame, currentPoint)) {
      return btn;
    }
  }
  return nil;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  CGPoint point = [self getCurrentTouch:touches];
  UIButton *btn = [self getCurrentBtnWithPoint:point];
  if (btn && btn.selected != YES) {
    btn.selected = YES;
    [self.btnsArray addObject:btn];
    NSLog(@" array is value %@",self.btnsArray);
  }
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  CGPoint movePoint = [self getCurrentTouch:touches];
  UIButton *btn = [self getCurrentBtnWithPoint:movePoint];
  if (btn && btn.selected !=YES) {
    btn.selected = YES;
    [self.btnsArray addObject:btn];
    NSLog(@"btn is value %@",self.btnsArray);
  }
  self.currentPoint = movePoint;
  [self setNeedsDisplay];
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  for (UIButton *btn in self.btnsArray) {
    [btn setSelected:NO];
  }
  NSMutableString *result = [NSMutableString string];
  for (UIButton *btn in self.btnsArray) {
    [result appendString: [NSString stringWithFormat:@"%ld",(long)btn.tag]];
  }
  switch (Amode) {
    case GestureSetPassword:{
      // Set gesture password 
      self.setPwdBlock([self pwdValue:result]);
    }
      break;
    case GestureResultPassword :{
      // Getting Gesture Password Results 
      if (self.sendReaultData) {
        if (self.sendReaultData(result) == YES) {
           NSLog(@"success");
          [self clear];
        }else{
          NSLog(@" Gesture error ");
        }

      }

    }
      break;

    default:
      break;
  }
  // Return results 
  [self clear];
}
#pragma mark  Delayed loading 
-(NSMutableArray *)btnsArray{
  if (_btnsArray == nil) {
    _btnsArray = [NSMutableArray array];
  }
  return _btnsArray;
}
-(NSMutableArray *)allBtnsArray{
  if (_allBtnsArray == nil) {
    _allBtnsArray = [NSMutableArray array];
  }
  return _allBtnsArray;
}

@end

Related articles: