Swift版仿支付寶的手勢解鎖潜秋,而且提供方法進(jìn)行參數(shù)修改蛔琅,能解決項目開發(fā)中所有手勢解鎖的開發(fā)

GYGestureUnlock


Swift版仿支付寶的手勢解鎖,而且提供方法進(jìn)行參數(shù)修改峻呛,能解決項目開發(fā)中所有手勢解鎖的開發(fā)

效果圖

2016-08-30 19_29_03.gif

此項目起因

  • 個人學(xué)習(xí)OC版手勢解鎖罗售,感覺只看源碼,沒有太大效果杀饵,于是乎將其完全照抄轉(zhuǎn)化為了神奇的Swift
  • 源OC版手勢解鎖
  • 為更深入的了解奇妙的Swift

項目簡介

  1. 文件包GYTools
    GYCircleConst:系統(tǒng)配置參數(shù)莽囤,錯誤語言提示,背景顏色等等切距,可根據(jù)自己的項目需要進(jìn)行修改
    GYCircleView:手勢View
    GYCircle:單個圓
    GestureViewController:設(shè)置密碼和登錄兩種情況的VC
    GestureVerifyViewController:驗證手勢和修改手勢的VC

  2. 核心實現(xiàn)方法
    GYCircleView:
    實現(xiàn)原理:每個圓添加tag拼接為字符串保存本地(項目中可傳至服務(wù)器)進(jìn)行比較
    //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)")
         }
     }
     //數(shù)組中最后一個對象的處理    circleSetLastObjectWithState(CircleState.CircleStateLastOneSelected)
     setNeedsDisplay()
      }
    
     override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
     currentPoint = CGPointZero
     let touch = (touches as NSSet).anyObject()
     
     //獲取手勢所在的點坐標(biāo)
     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
             // 判斷數(shù)組中是否包含此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
         
         // 如果是登錄或者驗證原手勢密碼  就改為對應(yīng)的狀態(tài)
         if self.type != CircleViewType.CircleViewTypeSetting {
             circlel.state = CircleState.CircleStateLastOneSelected
         }
         
             }
     
           //數(shù)組中最后一個對象的處理
           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
     }
     
     //手勢繪制結(jié)果處理
     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))
         
     }
     
     //手勢結(jié)束后是否錯誤回顯重繪朽缎,取決于是否延時清空數(shù)組和狀態(tài)復(fù)原
     errorToDisplay()
     
     }
         //MARK:- 每添加一個圓,就計算一次方向
         func calAngleAndconnectTheJumpedCircle() {
        
         if circleSet == nil || circleSet?.count <= 1 {
         return
        }
     
     //取出最后一個對象
     let lastOne = circleSet?.lastObject as! GYCircle
     
     //倒數(shù)第二個
     let lastTwo = circleSet?.objectAtIndex(self.circleSet!.count - 2) as! GYCircle
     
     //計算倒數(shù)第二個的位置
     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.計算角度(反正切函數(shù))
     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 {
         //把跳過的圓加到數(shù)組中,他的位置是倒數(shù)第二個
         if !(self.circleSet!.containsObject(centerCircle!)) {
             //插入數(shù)組中
             self.circleSet?.insertObject(centerCircle!, atIndex: (self.circleSet?.count)! - 1)
             //指定此圓的角度與上一個角度相同话肖。否則會造成移位
             centerCircle?.angle = lastTwo.angle
             
         }
        }
      
     }      
    

3.實現(xiàn)調(diào)用

  switch sender.tag {
    case 1:
        //設(shè)置手勢密碼
        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: "暫未設(shè)置手勢密碼,是否前往設(shè)置", delegate: self, cancelButtonTitle: "取消", otherButtonTitles: "設(shè)置")
            
            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導(dǎo)致崩潰
最后北秽,奉上源碼地址求Star,大家一起學(xué)習(xí),3Q。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末最筒,一起剝皮案震驚了整個濱河市贺氓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌床蜘,老刑警劉巖辙培,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邢锯,居然都是意外死亡扬蕊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門丹擎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尾抑,“玉大人,你說我怎么就攤上這事蒂培≡儆” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵护戳,是天一觀的道長翎冲。 經(jīng)常有香客問我,道長媳荒,這世上最難降的妖魔是什么府适? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮肺樟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逻淌。我一直安慰自己么伯,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布卡儒。 她就那樣靜靜地躺著田柔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骨望。 梳的紋絲不亂的頭發(fā)上硬爆,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機(jī)與錄音擎鸠,去河邊找鬼缀磕。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的袜蚕。 我是一名探鬼主播糟把,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼牲剃!你這毒婦竟也來了遣疯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤凿傅,失蹤者是張志新(化名)和其女友劉穎缠犀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聪舒,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡辨液,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了过椎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片室梅。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖疚宇,靈堂內(nèi)的尸體忽然破棺而出亡鼠,到底是詐尸還是另有隱情,我是刑警寧澤敷待,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布间涵,位于F島的核電站,受9級特大地震影響榜揖,放射性物質(zhì)發(fā)生泄漏勾哩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一举哟、第九天 我趴在偏房一處隱蔽的房頂上張望思劳。 院中可真熱鬧,春花似錦妨猩、人聲如沸潜叛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽威兜。三九已至,卻和暖如春庐椒,著一層夾襖步出監(jiān)牢的瞬間椒舵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工约谈, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留笔宿,地道東北人犁钟。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像措伐,于是被迫代替她去往敵國和親特纤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容