iOS 제스처 슬라이딩 잠 금 해제 기능 분석 실현

기록 하 다
일상생활 에서 우 리 는 제스처 가 미 끄 러 지 는 것 을 자주 만 날 수 있 습 니 다.즉,구 궁 격 입 니 다.이미 나타 난 지 오래 되 었 습 니 다.애플 의 지문 잠 금 해제 의 발전 에 따라 제스처 잠 금 해제 도 있 지만 지문 잠 금 해제 보다 편리 하지 않 기 때문에 사용 하 는 것 도 적 습 니 다.그러나 대부분 앱 에서 이 두 가지 방식 은 모두 공존 합 니 다.예 를 들 어 qq,위 챗,알 리 페 이 등 입 니 다.최근 프로젝트 에서 도 이런 수요 가 있 었 다.방금 완성 한 시간 을 틈 타 그 당시 의 생각 을 기록 했다.어떤 부분 은 제대로 이해 하지 못 했 을 수도 있 고 정 리 를 많이 해 야 한다.잡담 을 적 게 하고 중심 을 봐 야 한다.
기능 설명 은 그림 과 같다.대충 생각 을 말 해 보 자.이 기능 은 암호 에 해당 하 는 것 으로 양쪽 의 일치 에 사용 된다.교사 단 은 경로 생 성 비밀 번 호 를 설정 하고 현지 에 저장 하 며 학생 단 은 미끄럼 입력 으로 검증 한다.그리고 여러 가지 상황 에 따라 상부 의 label 이 여러 가지 힌트 정 보 를 주 었 습 니 다.여 기 는 원시 적 이 고 허름 한 demo 일 뿐 우리 가 가장 흔히 볼 수 있 는 기능 을 실 현 했 기 때문에 그 중의 정신 을 이해 하 는 데 중심 을 두 었 습 니 다.하하 하.

기능 모듈 분석
GIF 에 따 르 면 이 기능 을 몇 가지 부분 으로 간단하게 나 눌 수 있 습 니 다.첫 번 째 는 첫 번 째 페이지 입 니 다.ViewController 입 니 다.첫 번 째 페이지 에는 두 개의 Controller 가 있 는데 그것 이 바로 StudViewController 와 TeacViewController 가 서로 다른 기능 의 운반 체 로 나 눌 수 있 습 니 다.StudView Controller 에 서 는 세 부분 상하 status Label Gesture LockView clearbtn 으로 나 뉘 는데 그 중에서 Gesture LockView 는 제스처 잠 금 해제 인터페이스 이다.TeacviewController 에서 도 세 부분 으로 나 뉘 는데 status Label Gesture LockView BottomView 아래 의 bottomView 는 button resetBtn 리 셋 단추 와 sureBtn 확인 단추 로 나 뉜 다.대체적인 구 조 를 말 하고 다음 부분 으로 나 누 어 모든 기능 의 실현 방향 을 말 해 보 자.
해체 분석
먼저 Gesture LockView 라 는 view 컨트롤 을 말씀 드 리 겠 습 니 다.
우선.h 파일 에서
두 개의 매 거 진 을 정의 합 니 다.각각 양 끝 의 서로 다른 유형 을 정의 하 는 데 사 용 됩 니 다.stu 단 은 ResultKind Type 으로 그림 의 제스처 결 과 를 이 네 가지 로 분류 합 니 다.다음은 모두 사용 되 고 용 도 를 설명 합 니 다.teac 엔 드 는 TeacKind Type 으로 두 가지 유형 으로 나 뉜 다.

//            / /  4   
typedef NS_ENUM(NSUInteger, ResultKindType) {
  ResultKindTypeTrue,
  ResultKindTypeFalse,
  ResultKindTypeNoEnough,
  ResultKindTypeClear
};

typedef NS_ENUM(NSUInteger, TeacKindType) {
  TeacKindTypeNoEnough,
  TeacKindTypeTrue
};

프로 토 콜:제스처 가 바 뀌 었 을 때 전 달 된 전환 암 호 를 감청 하 는 데 사 용 됩 니 다.(이 암 호 는 button 의 tag 값 으로 표 시 됩 니 다.)제스처 가 바 뀌 었 기 때문에 NSMutableString 으로 밖으로 전 달 됩 니 다.

@protocol GestureLockDelegate <NSObject>

- (void)gestureLockView:(GestureLockView *)lockView drawRectFinished:(NSMutableString *)gesturePassword;

@end
속성:
  • @property (nonatomic, weak) id delegate;
  • @property (nonatomic, assign) BOOL isTeac;//교사 단 은 교사 단 인지 아 닌 지 를 검증 하 는 데 쓰 인 다.
    방법:
    
    - (void)clearLockView;//         
    
    - (void)checkPwdResult:(ResultKindType)resultType;//        
    
    - (void)checkTeacResult:(TeacKindType)resultType;//        
    
    .m 파일 에서(구체 적 으로 만 들 고 응용 하 는 방법)
    설명 변 수 는 아래 에서 사용 할 수 있 습 니 다:
    
    @interface GestureLockView ()
    
    @property (strong, nonatomic) NSMutableArray *selectBtns;//       
    @property (nonatomic, strong) NSMutableArray *errorBtns;//       
    @property(nonatomic, assign)BOOL finished;//    
    @property (nonatomic, assign) CGPoint currentPoint;//     
    @property (nonatomic, assign) ResultKindType resultType;//     
    @property (nonatomic, assign) TeacKindType teacResultType;//     
    
    @end
    
    게 으 른 로드 초기 화 배열
    
    - (NSMutableArray *)selectBtns {
      if (!_selectBtns) {
        _selectBtns = [NSMutableArray array];
      }
      return _selectBtns;
    }
    
    - (NSMutableArray *)errorBtns {
      if (!_errorBtns) {
        _errorBtns = [NSMutableArray array];
      }
      return _errorBtns;
    }
    
    하위 보기 초기 화:여기에서 9 개의 단 추 를 만 들 고 self 에 추가 하 며,self 에 UIPanGesture Recognizer*pan 제스처 를 추가 합 니 다.
    
    - (void)initSubviews {
      self.backgroundColor = [UIColor clearColor];
      UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
      [self addGestureRecognizer:pan];
      
      //  9   
      for (NSInteger i = 0; i < 9; i++) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.userInteractionEnabled = NO;
        [btn setImage:[UIImage imageNamed:@"sign_img_circle_n"] forState:UIControlStateNormal];
        [btn setImage:[UIImage imageNamed:@"sign_img_circle_s"] forState:UIControlStateSelected];
        btn.tag = i+1;
        [self addSubview:btn];
      }
    }
    인터페이스 레이아웃:
    
      CGFloat minWidth = MIN(self.bounds.size.height, self.bounds.size.width);
      CGFloat boundsWidth = self.bounds.size.width;
      CGFloat margin = (minWidth - cols * w) / (cols + 1);//  
      CGFloat xMargin = (boundsWidth-2*margin-3*w)/2;
    여기 서 이 부분 은 서로 다른 기종 에 적합 합 니 다.이 컨트롤 은 height - (void)layoutSubviews { [super layoutSubviews]; NSUInteger count = self.subviews.count; int cols = 3;// CGFloat x = 0,y = 0,w = 0,h = 0; if (SCREEN_WIDTH == 320) { w = 50; h = 50; } else { w = 60; h = 60; } CGFloat minWidth = MIN(self.bounds.size.height, self.bounds.size.width); CGFloat boundsWidth = self.bounds.size.width; CGFloat margin = (minWidth - cols * w) / (cols + 1);// CGFloat xMargin = (boundsWidth-2*margin-3*w)/2; CGFloat col = 0; CGFloat row = 0; for (int i = 0; i < count; i++) { col = i % cols; row = i / cols; if (i == 0 || i == 3 || i == 6) { x = xMargin; } else if (i == 1 || i == 4 || i == 7) { x = xMargin + w + margin; } else { x = xMargin + 2 * (margin+w); } y = (w+margin)*row; UIButton *btn = self.subviews[i]; btn.frame = CGRectMake(x, y, w, h); } } 제스처 에이전트 방법:제스처 에이전트 방법 에서 제스처 가 미 끄 러 지 는 위치의 변 화 를 감청 합 니 다.pan.state=UIGesture Recognizer StateBegan 이 미 끄 러 지기 시 작 했 을 때 오류 상 태 를 보 여 주 는 button 을 일반 초기 상태 로 바 꾸 고 self.errorBtns 배열 을 지 웁 니 다.장currentPoint = [pan locationInView:self];미 끄 러 질 때 현재 위치 point 를 검사 합 니 다.그 어 진 위치 가 button 범위 에 포함 되 어 있 으 면 button.selected==NO 라면 button.selected=YES;/선택 하고 button 을 self.selectBtns 배열 에 추가 합 니 다[self.selectBtns addObject:button];[self setNeedsDisplay]호출;방법 을 다시 그립 니 다.setNeedsDisplay 방법 시스템 을 호출 하면 draw React 방법 으로 인터페이스의 재 구성 을 자동 으로 호출 합 니 다.마지막 으로 손가락 을 놓 을 지 여부//감청 손가락 을 놓 을 지 여부 if(pan.state==UIGesture Recognizer StateEnded){self.finished=YES;}self.finished=YES;
    
    #pragma mark   
    - (void)pan:(UIPanGestureRecognizer *)pan {
      
      if (pan.state == UIGestureRecognizerStateBegan) {
        for (UIButton *btn in _errorBtns) {
          [btn setImage:[UIImage imageNamed:@"sign_img_circle_n"] forState:UIControlStateNormal];
          [btn setImage:[UIImage imageNamed:@"sign_img_circle_s"] forState:UIControlStateSelected];
        }
        [self.errorBtns removeAllObjects];
      }
      _currentPoint = [pan locationInView:self];
      
      for (UIButton *button in self.subviews) {
        if (CGRectContainsPoint(button.frame, _currentPoint)) {
          if (button.selected == NO) {
            //     
            button.selected = YES;//     
            [self.selectBtns addObject:button];
          } else {
            
          }
        }
      }
      
      //  
      [self setNeedsDisplay];
      //      
      if (pan.state == UIGestureRecognizerStateEnded) {
        self.finished = YES;
      }
    }
    
    설정 한 제스처 암호 전달 방법
    
    //         
    - (NSMutableString *)transferGestureResult {
      //       
      NSMutableString *result = [NSMutableString string];
      for (UIButton *btn in self.selectBtns) {
        [result appendFormat:@"%ld", btn.tag - 1];
      }
      return result;
    }
    
    양쪽 의 외부 작업 이 내부 상태 에 대한 변경:
    
    case ResultKindTypeFalse:
    _errorBtns = [NSMutableArray arrayWithArray:self.selectBtns];
    break;
    그림%1 개의 캡 션 을 편 집 했 습 니 다.errorBtns 에서 오류 단 추 를 넣 은 그룹
    
    case ResultKindTypeClear:
    {
    [[UIColor clearColor] set];
    for (int i = 0; i < self.errorBtns.count; i++) {
    UIButton *btn = [self.errorBtns objectAtIndex:i];
    [btn setImage:[UIImage imageNamed:@"sign_img_circle_n"] forState:UIControlStateNormal];
    }
    [self.errorBtns removeAllObjects];
    }
    break;
    외부 에서 상태 가'제거'로 바 뀌 었 을 때 경 로 를 투명 하 게 설정 하고 errorBtns 배열 의 button 배경 색 상 태 를 바 꾸 고 errorBtns 를 비 웁 니 다.여기 서 왜 이런 변 화 를 합 니까?이것 은 학생 측 에서 제거 작업 을 할 때 제스처 의 상태 가 finish 이 고 이것 은 후 에이전트 방법 이 끝 났 기 때 문 입 니 다.또한 clearLockView 방법 을 호출 할 때 selectBtns 배열 을 비 웠 기 때문에 setNeeds Display 가 호출 되 었 습 니 다.drawReact 가 다시 그 릴 때 if()가 감지 되 었 습 니 다.selectBtns.count == 0) return;더 이상 진행 하지 않 겠 습 니 다.
    
    //       
    - (void)checkPwdResult:(ResultKindType)resultType {
      self.resultType = resultType;
      switch (resultType) {
        case ResultKindTypeFalse:
          _errorBtns = [NSMutableArray arrayWithArray:self.selectBtns];
          break;
          case ResultKindTypeTrue:
          break;
          case ResultKindTypeNoEnough:
          break;
          case ResultKindTypeClear:
        {
          [[UIColor clearColor] set];
          for (int i = 0; i < self.errorBtns.count; i++) {
            UIButton *btn = [self.errorBtns objectAtIndex:i];
            [btn setImage:[UIImage imageNamed:@"sign_img_circle_n"] forState:UIControlStateNormal];
          }
          [self.errorBtns removeAllObjects];
        }
          break;
        default:
          break;
      }
      [self clearLockView];
    }
    //       
    - (void)checkTeacResult:(TeacKindType)resultType {
      self.teacResultType = resultType;
      switch (resultType) {
        case TeacKindTypeTrue:
          break;
        case TeacKindTypeNoEnough:{
          [self clearLockView];
        }
          break;
        default:
          break;
      }
    }
    
    제거 방법:self.finished=NO;프 록 시 를 통 해 값 을 외부 로 전달 하고 외부 에서 이 값 을 검사 한 결과 내용 의 resultType 을 바 꾸 었 다 면 이 때 는 draw React 방법 에 있 었 고 self.finished 방법 을 마 쳤 기 때 문 입 니 다.여기 서 NO 로 설정 한 것 은 다음 에 그 려 진 finished 상 태 를 바 꾸 기 위해 서 입 니 다.눈 에 띄 지 않 지만 썼 습 니 다.
    
    - (void)clearLockView {
      self.finished = NO;
      //         
      for (UIButton *btn in self.selectBtns) {
        //      
        btn.selected = NO;
      }
      [self.selectBtns removeAllObjects];
      //
      [self setNeedsDisplay];
    }
    베 어 셀 곡선 을 이용 하여 경 로 를 그립 니 다.해당 상태 에 따라 경로 색상,단추 색상 을 변경 합 니 다.시스템 이 이 방법 을 호출 할 때 다시 그립 니 다.다시 그립 니 다.self.selectBtns 배열 에서 선택 한 button 을 꺼 냅 니 다.button 이 첫 번 째 일 때 bezierPath 의 출발점[path moveToPoint:btn.center]으로 설정 합 니 다.나머지 단 추 는 경로[path addLineToPoint:btn.center]를 그립 니 다.여기 서 손가락 을 풀 었 는 지 여 부 를 판단 합 니 다.이 판단 에 서 는 논리 적 판단 이 많 습 니 다.대충 훑 어보 세 요.self.finished==YES 일 때 만 든 비밀 번 호 를 이전 성명 의 대 리 를 이용 하여 외부 에 전달 하여 검사 합 니 다.외부 에서 되 돌아 오 는 동작 상태 에 따라 self.isTeac 가 되 돌아 오 는 결과 상태 에 따라 판단 합 니 다.
    
    case TeacKindTypeNoEnough:
    {
    [[UIColor clearColor] set];
    }
    break;
    case TeacKindTypeTrue:
    {
    [[UIColor colorWithRed:94/255.0 green:195/255.0 blue:49/255.0 alpha:0.8] set];
    }
    
    그림 의 점 이 4 개 미 만 이면 선택 한 점 을 지우 고 경로 의 색 을 투명 하 게 그립 니 다(또는 성능 을 고려 하면 배경 색 과 같은 색 을 사용 하 는 것 이 좋 습 니 다).그림 이 완성 되면'녹색'으로 채 웁 니 다.여기 서 저 는 교사 가 그 려 진 경 로 를 잘 모 르 는 경 로 를 선택 하여 볼 수 있 습 니 다.
    학생 쪽 이 라면 올 바른 제거 경 로 를 그립 니 다.'빨간색'표지 경 로 를 잘못 사용 하고 잘못된 단 추 를 담 은 배열 self.errorBtns 에서 단 추 를 꺼 내 상 태 를 바 꿉 니 다.
    
    switch (self.resultType) {
    case ResultKindTypeTrue:
    {
    //  
    [[UIColor clearColor] set];
    }
    break;
    case ResultKindTypeFalse:
    {
    //  
    [[UIColor redColor] set];
    for (int i = 0; i < self.errorBtns.count; i++) {
    UIButton *btn = [self.errorBtns objectAtIndex:i];
    [btn setImage:[UIImage imageNamed:@"sign_img_circle_p"] forState:UIControlStateNormal];
    }
    break;
    case ResultKindTypeNoEnough:
    {
    [[UIColor clearColor] set];
    }
    break;
    case ResultKindTypeClear:
    break;
    default:
    break;
    }
    
    그 다음 에 finish 가 없 으 면 경 로 를 그립 니 다.path 에 대해 관련 설정 을 합 니 다.
    
    - (void)drawRect:(CGRect)rect {
      if (_selectBtns.count == 0) return;
      //             
      UIBezierPath *path = [UIBezierPath bezierPath];
      for (int i = 0; i < self.selectBtns.count; i ++) {
        UIButton *btn = self.selectBtns[i];
        if (i == 0) {
          [path moveToPoint:btn.center]; //     
        } else {
          [path addLineToPoint:btn.center];
        }
      }
      
      //        
      if (self.finished) {
        //   
        NSMutableString *pwd = [self transferGestureResult];//       
        [[UIColor colorWithRed:94/255.0 green:195/255.0 blue:49/255.0 alpha:0.8] set];
        if ([self.delegate respondsToSelector:@selector(gestureLockView:drawRectFinished:)]) {
          [self.delegate gestureLockView:self drawRectFinished:pwd];
        }
        
        if (self.isTeac) {
          //   
          switch (self.teacResultType) {
            case TeacKindTypeNoEnough:
            {
              [[UIColor clearColor] set];
            }
              break;
            case TeacKindTypeTrue:
            {
              [[UIColor colorWithRed:94/255.0 green:195/255.0 blue:49/255.0 alpha:0.8] set];
            }
              break;
            default:
              break;
          }
        } else {
          switch (self.resultType) {
            case ResultKindTypeTrue:
            {
              //  
              [[UIColor clearColor] set];
            }
              break;
            case ResultKindTypeFalse:
            {
              //  
              [[UIColor redColor] set];
              for (int i = 0; i < self.errorBtns.count; i++) {
                UIButton *btn = [self.errorBtns objectAtIndex:i];
                [btn setImage:[UIImage imageNamed:@"sign_img_circle_p"] forState:UIControlStateNormal];
              }
              break;
            case ResultKindTypeNoEnough:
              {
                [[UIColor clearColor] set];
              }
              break;
            case ResultKindTypeClear:
              break;
            default:
              break;
            }
          }    
        }
      } else {
        [path addLineToPoint:self.currentPoint];
        [[UIColor colorWithRed:94/255.0 green:195/255.0 blue:49/255.0 alpha:0.8] set];
      }
      path.lineWidth = 1;
      path.lineJoinStyle = kCGLineCapRound;
      path.lineCapStyle = kCGLineCapRound;
      [path stroke];
    }
    
    ViewController
    이것 은 비교적 이해 하기 쉽다.각각 두 개의 화면 을 건너뛰다.
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      if (indexPath.row == 0) {
        TeacViewController *vc = [[TeacViewController alloc] init];
        [self.navigationController pushViewController:vc animated:YES];
      } else {
        StudViewController *vc = [[StudViewController alloc] init];
        [self.navigationController pushViewController:vc animated:YES];
      }
    }
    
    TeacViewController
    주요 응용 프로그램 은 Gesture LockView Delegate 를 호출 하여 암 호 를 받 아들 이 고 검증 하 는 것 입 니 다.
    
    #pragma mark gestureLockView    
    - (void)gestureLockView:(GestureLockView *)lockView drawRectFinished:(NSMutableString *)gesturePassword {
      [self createGesturesPassword:gesturePassword];
    }
    
    //      
    - (void)createGesturesPassword:(NSMutableString *)gesturePassword {
      if (self.lastGesturePsw.length == 0) {
        if (gesturePassword.length < 4) {
          self.lastGesturePsw = nil;
          [self.gestureLockView checkTeacResult:TeacKindTypeNoEnough];
          self.statusLabel.text = @"    4  ,    ";
          [self shakeAnimationForView:self.statusLabel];
          return;
        }
        self.lastGesturePsw = gesturePassword;
        [self.gestureLockView checkTeacResult:TeacKindTypeTrue];
        NSLog(@"---%@", self.lastGesturePsw);
        self.statusLabel.text = [NSString stringWithFormat:@"   %@", gesturePassword];
      }
    }
    
    
    두 단추 의 클릭 이벤트
    
    #pragma mark       
    //    
    - (void)resetBtnClick:(UIButton *)btn {
      self.lastGesturePsw = nil;
      [TeacViewController addGesturePassword:@""];
      [self.gestureLockView checkTeacResult:TeacKindTypeNoEnough];
      self.statusLabel.text = @"       ";
      NSLog(@"resetPwd == %@, resetUserDefaultsPwd == %@", self.lastGesturePsw, [TeacViewController gesturePassword]);
    }
    //    
    - (void)sureBtnClick:(UIButton *)btn {
      if (!self.lastGesturePsw) {
        self.statusLabel.text = @"       ";
        return;
      }
      [TeacViewController addGesturePassword:self.lastGesturePsw];
      [self.gestureLockView checkTeacResult:TeacKindTypeTrue];
      self.statusLabel.text = @"      ";
      NSLog(@"resetPwd == %@, resetUserDefaultsPwd == %@", self.lastGesturePsw, [TeacViewController gesturePassword]);
    //  [self.navigationController popViewControllerAnimated:YES];
    }
    
    로 컬 저장 소 로 시 뮬 레이 션 하기
    
    #pragma mark       
    + (void)deleteGestuesPassword {
      [[NSUserDefaults standardUserDefaults] removeObjectForKey:GESPWD];
      [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    + (void)addGesturePassword:(NSString *)gesturePassword {
      [[NSUserDefaults standardUserDefaults] setObject:gesturePassword forKey:GESPWD];
      [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    + (NSString *)gesturePassword {
      return [[NSUserDefaults standardUserDefaults] objectForKey:GESPWD];
    }
    
    
    StudViewController
    Gesture LockDelegate 에이전트 방법 및 현재 제스처 암호 와 로 컬 에 저 장 된 교사 측 암 호 를 검사 합 니 다.
    
    #pragma mark         
    - (void)gestureLockView:(GestureLockView *)lockView drawRectFinished:(NSMutableString *)gesturePassword {
      [self validateGesturePassword:gesturePassword];
    }
    
    //      
    - (void)validateGesturePassword:(NSMutableString *)gesturePassword {
      
      if (gesturePassword.length < 4) {
        self.statusLabel.text = @"    4  ,    ";
        [self.gestureLockView checkPwdResult:ResultKindTypeNoEnough];
        [self shakeAnimationForView:self.statusLabel];
        return;
      }
      self.lastGesturePsw = gesturePassword;
      
      
      /*      */
      NSLog(@"validPwd == %@, validUserDefaultsPwd == %@", self.lastGesturePsw, [StudViewController gesturePassword]);
      static NSInteger errorCount = 5;
      
      if ([self.lastGesturePsw isEqualToString:[StudViewController gesturePassword]]) {
        [self.gestureLockView checkPwdResult:ResultKindTypeTrue];
        self.statusLabel.text = @"      ";
        [self shakeAnimationForView:self.statusLabel];
      } else {
        [self.gestureLockView checkPwdResult:ResultKindTypeFalse];
        errorCount = errorCount - 1;
        if (errorCount == 0) {
          //    5 
          self.statusLabel.text = @"       ";
          errorCount = 5;
          return;
        }
        self.statusLabel.text = [NSString stringWithFormat:@"    ,       %ld ", errorCount];
        [self shakeAnimationForView:self.statusLabel];
      }
    }
    
    
    지우 기 단 추 를 누 르 면 이벤트 변경 self.gesture LockView 의 resultType 을 누 르 면 인터페이스 재 설정 등 을 조정 합 니 다.
    
    - (void)clearBtnClick:(UIButton *)btn {
      self.statusLabel.text = @"  !!!";
      [self.gestureLockView checkPwdResult:ResultKindTypeClear];
      [self shakeAnimationForView:self.statusLabel];
    }
    로 컬 저장 소:여기 도 로 컬 저장 소 와 교사 측 이 대응 합 니 다.(사실은 따로 포장 할 수 있 습 니 다)
    
    #pragma mark       
    + (void)deleteGestuesPassword {
      [[NSUserDefaults standardUserDefaults] removeObjectForKey:GESPWD];
      [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    + (void)addGesturePassword:(NSString *)gesturePassword {
      [[NSUserDefaults standardUserDefaults] setObject:gesturePassword forKey:GESPWD];
      [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    + (NSString *)gesturePassword {
      return [[NSUserDefaults standardUserDefaults] objectForKey:GESPWD];
    }
    
    이상 은 바로 이 기능 이 실현 되 는 대체 적 인 절차 입 니 다.생각 을 정리 한 결과 아직도 명확 합 니 다.그 당시 에 할 때 도 구 덩이 를 파 서 구 덩이 를 메 웠 습 니 다.이렇게 자신의 생각 을 쓰 면 정말 얻 은 것 이 있 습 니 다.자신 이 더욱 발전 하 기 를 바 랍 니 다.만약 에 여기 서 불합리한 부분 이 있다 고 생각 되면 언제든지 저 와 소통 하 는 것 을 환영 합 니 다.
    소스 코드 연결:https://github.com/irembeu/LGJGestureLockDemo.git
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
  • 좋은 웹페이지 즐겨찾기