swiftはBlocksKitがなくて、私は我慢できなくて自分でClosuresKitを書きました

4147 ワード

OC時代、私はよくBlocksKitを使っていましたが、RACが導入される前に、blockskitはコードを優雅にしました.しかし、swiftがリリースされると、swiftはゲートの強いタイプの言語であるため、runtime関連の方法は推奨されません.swiftではruntimeのいくつかの特性を使用するには@objcのような特別な宣言が必要です.これによりblockskitにはswiftバージョンはありません.しかし、runtimeのいくつかのものを取り除いても、blockskitにはいくつかの拡張方法が実用的です.だから、私は自分でblockskitに近い一般的な方法を考えることができることを書きました:ClosuresKit.主に以下の3つの部分の拡張があります
Foundation
コレクションタイプが追加されたapi
  • cs_matchは受信した閉パケットに基づいて一致する1つのデータを探し出し、filterは1つの集合を返し、matchは1つのデータだけを返すのが違いです.例:
  •     let testSequence = [2,5,6,9]
      
        func testMatch() {
            let result = testSequence.cs_match { (value) -> Bool in
                return value == 5
            }
            assert(result==5,"match failed")
        }
    
  • cs_anyパラメータは前述と同様にブール値を返し,受信した閉パケットによって集合中にデータがこの閉パケットに合致するか否かを判断する.
  • cs_allパラメータは前述と同様にブール値を返し,受信した閉パケットにより集合中のすべてのデータがこの閉パケットに合致するか否かを判断する.
  • cs_noneパラメータは前述と同様にブール値を返し,受信した閉パケットによって集合中にこの閉パケットに合致するデータが1つもないか否かを判断する.

  • NSObjectが容易に関連するオブジェクト
    NSObjectのobjc_setAssociatedObjectをカプセル化する方法.いくつかのapiの違いは、reatian、copy、weakなど、関連するポリシーが異なることです.
    class AssocaitedObjectTests: XCTestCase {
        static var identifier = "identifier"
    
        func testCopyAssociateValue(){
            let test:NSMutableString="first"
            let view = UIView()
            view.cs_associateCopyOfValue(test, key: &AssocaitedObjectTests.identifier)
            test.appendString("t")
            let result = view.cs_associateValueForKey(&AssocaitedObjectTests.identifier) as! NSString
            assert(result=="first","CopyAssociateValue failed")
        }
        
    }
    

    これは、ユニットテストに書かれた関連オブジェクトポリシー用copyのサンプルコードです.
    通知cs_addNotificationObserverForNameによって、ある通知に対する処理を容易に追加することができる.
     func testObserverNotification() {
            let notificationName = "Test"
            cs_addNotificationObserverForName(name: "Test", object: nil) { (notification) in
                assert(notification.userInfo!["value"] as! String == "param",#function)
            }
            NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: self,userInfo:["value":"param"])
        }
    
    

    NSTimer
    timerを追加するときに閉パケットを入力してコールバックを直接処理できます.サンプルコード:
        var count=0
        var timer:NSTimer?
    
        func testTimerWithtimeInterval() {
            timer = NSTimer.cs_scheduledTimerWithTimeInterval(1, repeats: false, userInfo: ["key":"value"]) {[unowned self] (timer) in
                assert(timer.userInfo!["key"]=="value", #function)
                print("times:\(self.count)")
            }
            timer!.fire()
        }
    

    UIKIt
    UIcontrolにUIcontrol Eventsの処理を容易にする方法cs_addEventHandlerForEventsを追加した.例は以下の通りである.
       btn.cs_addEventHandlerForEvents(.TouchUpInside) { (sender) in
                print("TouchUpInside")
            }
    

    UIGesture
    UIViewに便利な直接ジェスチャーを追加することができて、チェーン式のプログラミングをサポートして、ジェスチャーを追加する時その閉パッケージの中で配置することができて、連続的にいくつかの異なる状態を処理することができます:
         label.cs_addPanGesture { (gestureRecognizer) in
                gestureRecognizer.maximumNumberOfTouches=2
            }.whenBegan { (gestureRecognizer) in
                print("began")
            }
    

    構成を使用しない場合は、構成された閉パッケージを直接空にすることができます.
           label.cs_addPanGesture().whenChanged { (gestureRecognizer) in
                print("changed")
            }
    

    また、複数のステータスに同じプロセスクローズを同時に追加することもできます.
    lbState.nc_addPanGesture().whenStatesHappend([.Ended,.Changed]) { (gestureRecognizer) -> Void in
                
            }
    

    tapとswipeには、2つのショートカット処理方法が追加されています.
        label.cs_whenTapped { (tapGestureRecognizer) in
                print("tapped")
            }
            
         view.cs_whenSwipedInDirection(.Down) { (gestureRecognizer) in
                print("down")
            }
    

    現在思いついているapiはこれだけで、issueに直接言及する必要があるものがあれば、私はすぐに処理します.pull requestも直接提出することを歓迎します.
    startのサポートを歓迎します.https://github.com/lacklock/ClosuresKit