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閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容