欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS实现手势密码功能

程序员文章站 2024-02-14 16:53:16
手势密码实现 手势密码 一般常常用于金融项目,做的是安全相关的业务。具体实现如下思路,我把它分为view层和逻辑层。我将数据层合并到view层中了,最好是加上数据层用于处...

手势密码实现

手势密码 一般常常用于金融项目,做的是安全相关的业务。具体实现如下思路,我把它分为view层和逻辑层。我将数据层合并到view层中了,最好是加上数据层用于处理加密的密码和密码的存储

view层

view层主要处理,包括(九个按钮)touchesbegan,touchesmoved,touchesended,点与点之间画线,手指滑动画线,画线主要是在drawrect中重绘,提到这里必须不能忘记setneedsdisplay这个方法。还要记录经过的按钮btnsarray(存放按钮的数组),这个 可以和相关的具体值做映射,也可以直接设置btn 的tag,还要添加完成绘画的回调。提供给逻辑层去处理。

逻辑层

用于处理完成交互后的业务,包括(请求接口,异常逻辑显示,等等)
具体的demo点这里

具体的code:
view.h

//
// yhgesturepasswordview.h
// 手势密码
//
// created by mrlee on 2017/3/5.
// copyright © 2017年 mrlee. all rights reserved.
//
typedef enum {
  gesturesetpassword, //设置手势密码
  gestureresultpassword //已有手势密码教验
} passwordstate;
//设置密码的3种状态
typedef enum {
  fristpwd, //第一次设置密码
  pwdnovalue, //二次设置密码不一致
  setpwdsuccess, //设置密码成功
  other
}setpwdstate;

#import <uikit/uikit.h>

@interface yhgesturepasswordview : uiview
/** btn图片*/
@property (nonatomic,strong)uiimage *btnimage;

///选中的图片
@property (nonatomic,strong)uiimage *btnselectimage;

///划线颜色
@property (nonatomic,strong)uicolor *linecolor;

/** 解锁手势完成之后判断结果时调用的block */
@property (nonatomic,copy)bool (^sendreaultdata)(nsstring *str);

//设置手势密码
@property(nonatomic,copy)void(^setpwdblock)(setpwdstate pwdstate);


// init
-(instancetype)initwithframe:(cgrect)frame withstate:(passwordstate)state;

@end

view.m

//
// yhgesturepasswordview.m
// 手势密码
//
// created by mrlee on 2017/3/5.
// copyright © 2017年 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(){
  /** 判断是当设置密码用,还是解锁密码用*/
  passwordstate amode;
}
/** 所有的按钮集合*/
@property (nonatomic,strong)nsmutablearray * allbtnsarray;

/** 解锁时手指经过的所有的btn集合*/
@property (nonatomic,strong)nsmutablearray * btnsarray;

/** 手指当前的触摸位置*/
@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{
  // 每次调用这个方法的时候如果背景颜色是default会产生缓存,如果设置了颜色之后就没有缓存,绘制之前需要清除缓存
  cgcontextref ctx = uigraphicsgetcurrentcontext();
  cgcontextclearrect(ctx, rect);//清空上下文
  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)) {//如果起点不是cgpointzero的话才来划线
    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 绘制九宫格
  [self drawui];


}
#pragma mark private method
-(void)drawui{
  for (int index = 0; index<self.allbtnsarray.count; index ++) {
    //拿到每个btn
    uibutton *btn = self.subviews[index];

    //设置frame
    cgfloat btnw = 74;
    cgfloat btnh = 74;
    cgfloat margin = (screen_width - (btnw *3))/4;
    //x = 间距 + 列号*(间距+btnw)
    cgfloat btnx = margin + (index % 3)*(margin + btnw);
    cgfloat btny = margin + (index / 3)*(margin + btnh);

    btn.frame = cgrectmake(btnx, btny, btnw, btnh);
  }

}
//设置密码
-(setpwdstate)pwdvalue:(nsstring *)str{
  if ([[nsuserdefaults standarduserdefaults] objectforkey:@"pwdvalue"] == nil) {
    //第一次设置
    [[nsuserdefaults standarduserdefaults] setvalue:str forkey:@"pwdvalue"];
    return fristpwd;
  }
  if ([str isequaltostring: [[nsuserdefaults standarduserdefaults]objectforkey:@"pwdvalue"]]) {
    //设置成功
    return setpwdsuccess;
  }
  if (![str isequaltostring: [[nsuserdefaults standarduserdefaults]objectforkey:@"pwdvalue"]]) {
    //二次设置不一样
    return pwdnovalue;
  }

  return other;

}
//清空
-(void)clear{
  [self.btnsarray removeallobjects];
  self.currentpoint = cgpointzero;
  [self setneedsdisplay];
  self.linecolor = [uicolor greencolor];
  self.userinteractionenabled = yes;
}
//获取触摸的点
-(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:{
      //设置手势密码
      self.setpwdblock([self pwdvalue:result]);
    }
      break;
    case gestureresultpassword :{
      //获取手势密码结果
      if (self.sendreaultdata) {
        if (self.sendreaultdata(result) == yes) {
           nslog(@"success");
          [self clear];
        }else{
          nslog(@"手势有误");
        }

      }

    }
      break;

    default:
      break;
  }
  //返回结果
  [self clear];
}
#pragma mark 延时加载
-(nsmutablearray *)btnsarray{
  if (_btnsarray == nil) {
    _btnsarray = [nsmutablearray array];
  }
  return _btnsarray;
}
-(nsmutablearray *)allbtnsarray{
  if (_allbtnsarray == nil) {
    _allbtnsarray = [nsmutablearray array];
  }
  return _allbtnsarray;
}

@end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。