Swift版仿支付宝的手势解锁,而且提供方法进行参数修改,能解决项目开发中所有手势解锁的开发

GYGestureUnlock


Swift版仿支付宝的手势解锁,而且提供方法进行参数修改,能解决项目开发中所有手势解锁的开发

效果图

2016-08-30 19_29_03.gif

此项目起因

  • 个人学习OC版手势解锁,感觉只看源码,没有太大效果,于是乎将其完全照抄转化为了神奇的Swift
  • 源OC版手势解锁
  • 为更深入的了解奇妙的Swift

项目简介

  1. 文件包GYTools
    GYCircleConst:系统配置参数,错误语言提示,背景颜色等等,可根据自己的项目需要进行修改
    GYCircleView:手势View
    GYCircle:单个圆
    GestureViewController:设置密码和登录两种情况的VC
    GestureVerifyViewController:验证手势和修改手势的VC

  2. 核心实现方法
    GYCircleView:
    实现原理:每个圆添加tag拼接为字符串保存本地(项目中可传至服务器)进行比较
    //MARK:- 手势方法 began - moved - end
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    gestureEndResetMembers()
    currentPoint = CGPointZero
    let touch = (touches as NSSet).anyObject()

     let point = touch?.locationInView(self)
     (subviews as NSArray).enumerateObjectsUsingBlock { (circle, idx, stop) in
         let cir = circle as! GYCircle
         
         if CGRectContainsPoint(cir.frame, point!) {
             cir.state = CircleState.CircleStateSelected
             self.circleSet?.addObject(cir)
             print("添加子View的tag:\(cir.tag)")
         }
     }
     //数组中最后一个对象的处理    circleSetLastObjectWithState(CircleState.CircleStateLastOneSelected)
     setNeedsDisplay()
      }
    
     override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
     currentPoint = CGPointZero
     let touch = (touches as NSSet).anyObject()
     
     //获取手势所在的点坐标
     let point = touch?.locationInView(self)
     (subviews as NSArray).enumerateObjectsUsingBlock { (circle, idx, stop) in
     
     //我说
     let cir = circle as! GYCircle
     if CGRectContainsPoint(cir.frame, point!) {
             
             //此处脑残了 self.circleSet?.containsObject(cir) != nil
             // 判断数组中是否包含此view 包含不添加 不包含则添加
             if self.circleSet!.containsObject(cir) {
                 //                    print("添加子View的tag:\(cir.tag)")
                 //                    self.circleSet?.addObject(cir)
                 //                    self.calAngleAndconnectTheJumpedCircle()
             } else {
                 self.circleSet?.addObject(cir)
                 
                 // move过程中的连线(包含跳跃连线的处理)
                 self.calAngleAndconnectTheJumpedCircle()
             }
         } else {
            self.currentPoint = point
         }
         
          }
     
           guard (self.circleSet != nil) else {
          return
          }
          
           (self.circleSet! as NSArray).enumerateObjectsUsingBlock { (circle, idx, stop) in
         
         let circlel = circle as! GYCircle
         circlel.state = CircleState.CircleStateSelected
         
         // 如果是登录或者验证原手势密码  就改为对应的状态
         if self.type != CircleViewType.CircleViewTypeSetting {
             circlel.state = CircleState.CircleStateLastOneSelected
         }
         
             }
     
           //数组中最后一个对象的处理
           self.circleSetLastObjectWithState(CircleState.CircleStateLastOneSelected)
     
            setNeedsDisplay()
           }
    
          override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
          self.hasClean = false
          guard self.circleSet != nil else {
         return
     }
     let gesture = self.getGestureResultFromCircleSet(self.circleSet!)
     
     let length = gesture.length
     
     if length == 0 {
         return
     }
     
     //手势绘制结果处理
     switch self.type! {
     case CircleViewType.CircleViewTypeSetting:
         gestureEndByTypeSettingWithGesture(gesture, length: CGFloat(length))
         break
     case CircleViewType.CircleViewTypeLogin:
         gestureEndByTypeLoginWithGesture(gesture, length: CGFloat(length))
     case CircleViewType.CircleViewTypeVerify:
         gestureEndByTypeVerifyWithGesture(gesture, length: CGFloat(length))
         
     }
     
     //手势结束后是否错误回显重绘,取决于是否延时清空数组和状态复原
     errorToDisplay()
     
     }
         //MARK:- 每添加一个圆,就计算一次方向
         func calAngleAndconnectTheJumpedCircle() {
        
         if circleSet == nil || circleSet?.count <= 1 {
         return
        }
     
     //取出最后一个对象
     let lastOne = circleSet?.lastObject as! GYCircle
     
     //倒数第二个
     let lastTwo = circleSet?.objectAtIndex(self.circleSet!.count - 2) as! GYCircle
     
     //计算倒数第二个的位置
     let last_1_x = lastOne.center.x
     let last_1_y = lastOne.center.y
     
     let last_2_x = lastTwo.center.x
     let last_2_y = lastTwo.center.y
     
     //1.计算角度(反正切函数)
     let angle = atan2(Float(last_1_y) - Float(last_2_y), Float(last_1_x) - Float(last_2_x)) + Float( M_PI_2)
     lastTwo.angle = CGFloat(angle)
     print(lastTwo.angle)
     //2.处理跳跃连线
     let center = centerPointWithPointOneandTwo(lastOne.center, pointTwo: lastTwo.center)
     
     let centerCircle = self.enumCircleSetToFindWhichSubviewContainTheCenterPoint(center)
     
     if centerCircle != nil {
         //把跳过的圆加到数组中,他的位置是倒数第二个
         if !(self.circleSet!.containsObject(centerCircle!)) {
             //插入数组中
             self.circleSet?.insertObject(centerCircle!, atIndex: (self.circleSet?.count)! - 1)
             //指定此圆的角度与上一个角度相同。否则会造成移位
             centerCircle?.angle = lastTwo.angle
             
         }
        }
      
     }      
    

3.实现调用

  switch sender.tag {
    case 1:
        //设置手势密码
        let gesture = GestureViewController()
        gesture.type = GestureViewControllerType.Setting
        
        navigationController?.pushViewController(gesture, animated: true)
        
        break
    case 2:
        //登录手势密码
        print(GYCircleConst.getGestureWithKey(gestureOneSaveKey))
        if GYCircleConst.getGestureWithKey(gestureFinalSaveKey) != nil {
            
            let gestureVC = GestureViewController()
            gestureVC.type = GestureViewControllerType.Login
            
            navigationController?.pushViewController(gestureVC, animated: true)
            
            
        } else {
            let  alertView = UIAlertView(title: "温馨提示", message: "暂未设置手势密码,是否前往设置", delegate: self, cancelButtonTitle: "取消", otherButtonTitles: "设置")
            
            alertView.show()
        }
        
        break
    case 3:
        //验证手势密码
        let gestureVerifyVc  = GestureVerifyViewController()
        navigationController?.pushViewController(gestureVerifyVc, animated: true)
        
        break
    case 4:
        //修改手势密码
        let gestureVerifyVc  = GestureVerifyViewController()
        gestureVerifyVc.isToSetNewGesture = true
        navigationController?.pushViewController(gestureVerifyVc, animated: true)
        break           

4.遇到的swift的坑
1)各处nil
2)Swift的重写GET和SET方法
3)init初始化
4)一些可选值未初始化时会nil导致崩溃
最后,奉上源码地址求Star,大家一起学习,3Q。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容