Day 7クローズドパッケージ(Closures)

9738 ワード

このページには、•閉パッケージ式•閉パッケージに続く•値取得•閉パッケージが参照タイプ•脱出閉パッケージ•自動閉パッケージ
                ,            。Swift       C   Objective-C      (blocks)                    。
                              。          。 Swift                      。
     
                               ,            :
     •                      
     •                           
     •                                       
     
     Swift              ,               ,      :
     •                
     •           ,            return     •       
     •       

1、閉パッケージ式
  • 閉包式構文閉包式構文は、
     { (parameters) -> returnType in
    statements
    }
  • の一般的な形式である.
    閉パケット式パラメータはin-outパラメータであってもよいが、デフォルト値は設定できない.名前付きの可変パラメータも使用できます(注:ただし、可変パラメータがパラメータリストの最後のビットに配置されていない場合は、閉パッケージを呼び出すときにコンパイラがエラーを報告します.)メタグループは、パラメータと戻り値としても使用できます.
        let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
       //    :(String, String)->Bool
        var reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
            return s1 > s2
        })
    

    閉パケットの関数体部分はキーワードinによって導入される.このキーワードは、閉パケットのパラメータと戻り値タイプの定義が完了し、閉パケット関数体が開始することを示します.この閉パッケージの関数体部分はこのように短いため、1行のコードに書き換えることができます.
    reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 })
    print(reversedNames)
  • は、合計閉パッケージ//閉パッケージタイプを定義します:(Int,Int)->(Int)
     let add:(Int,Int)->(Int) = {
    (a,b) in
    return a + b;
    }
    // ,
    let result = add(1100, 200);
    //
    print("result=(result)");
    パラメータと実行するコード(code)はキーワード「in」で区切られています.閉パッケージにパラメータがない場合は、「()in」は直接省略できます.
    1、{
    ( 1, 2) in
    //code
    }
    2、{
    //code
    }
  • コンテキスト推定タイプ
  • ソート閉包関数はsorted(by:)メソッドのパラメータとして渡されるため,Swiftはそのパラメータと戻り値のタイプを推定できる.sorted(by:)メソッドは文字列配列によって呼び出されるため、そのパラメータは(String,String)->Boolタイプの関数でなければなりません.これは,(String,String)およびBoolタイプが閉パケット式定義の一部として必要でないことを意味する.すべてのタイプが正確に推定できるため、戻り矢印(->)とパラメータの周囲の括弧を省略してもよい:reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
  • 単一式閉包暗黙戻り単行式閉包はreturnキーワードを省略する暗黙戻り単行式の結果を暗黙的に返すことができ、上記のバージョンの例はreversedName=namesと書き換えることができる.sorted(by:{s 1,s 2 in s 1>s 2})この例では、sorted(by:)メソッドのパラメータタイプは、閉パケットがBoolタイプ値を返さなければならないことを明確にしている.閉包関数体には単一の式(s 1>s 2)しか含まれていないため、この式はBoolタイプ値を返すので、ここでは曖昧ではなく、returnキーワードは省略することができる.
  • パラメータ名略語Swiftは自動的にインライン閉パケットにパラメータ名略語機能を提供し、閉パケットのパラメータを$0,$1,$2で直接呼び出すことができます.閉パッケージ式でパラメータ名の略語を使用すると、閉パッケージ定義でパラメータリストを省略でき、対応するパラメータ名の略語のタイプは関数タイプで推定されます.inキーワードも同様に省略することができるが、このときの閉包式は完全に閉包関数体で構成する:reversedName=names.sorted(by:{$0>$1})この例では、$0および$1は、閉パケットの最初のStringタイプと2番目のStringタイプのパラメータを表す.キーワードtypealiasで閉じたパケットのデータ型を宣言することもできます.閉じたパケット型AddBlock
    typealias AddBlock = (Int,Int)->(Int);
    let add:AddBlock = {
    (a,b) in
    return a + b;
    }
    let result = add(1100, 200);
    print("result=(result)");
  • を宣言します.
  • 演算子メソッドSwiftのStringタイプは、1つの関数として2つのStringタイプのパラメータを受け入れ、Boolタイプの値を返す、番号(>)より大きい文字列実装を定義する.これはsorted(by:)メソッドのパラメータに必要な関数タイプにぴったりです.したがって、大きな番号を簡単に渡すことができます.Swiftは、より大きな文字列関数を使用して実装したいと自動的に推定します.reversedName=namesです.sorted(by: >) print(reversedNames);//["Ewa", "Daniella", "Chris", "Barry", "Alex"]

  • 2、末尾の閉パケット長い閉パケット式を最後のパラメータとして関数に渡す必要がある場合は、末尾の閉パケットを使用して関数の可読性を向上させることができます.後続の閉パケットは、関数カッコの後に書かれた閉パケット式であり、関数は最後のパラメータとして呼び出すことをサポートします.後続の閉パッケージを使用する場合は、パラメータラベルを書く必要はありません.
        
    func someFunctionThatTakesAClosure(closure: () -> Void) {
            //      
        }
        //                 
        someFunctionThatTakesAClosure(closure: {
        //        
        })
        //                 
        someFunctionThatTakesAClosure() {
        //       
        }
    sorted(by:)メソッドパラメータの ソート パケットは、 のように き えることができます.
        reversedNames = names.sorted() { $0 > $1 }
    

    が またはメソッドの のパラメータである 、 の を する は、()を することもできます:reversedNames = names.sorted { $0 > $1 } じたパケットが に くて1 で くことができない 、 じたパケットに くことが に になる として、SwiftのArrayタイプにはmap(:)メソッドがあり、このメソッドは じたパケット をその のパラメータとして する. は、 の に1 び され、その がマッピングした を します. なマッピング と り タイプは、 パケットで されます. に される パケットが に されると、map(:)メソッドは、 の の に するマッピングされた を む しい を します. の では、map(:)メソッドで の パケットを してIntタイプ [16,58,510]をStringタイプに する を む に する を します["OneSix"、"FiveEight"、"FiveOneZero"]:
        let digitNames = [
            0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
            5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
        ]
        let numbers = [16, 58, 510]
        
        let strings = numbers.map {
            (number) ->String in
                var number = number
                var output = ""
            repeat {
                output = digitNames[number % 10]! + output
                number /= 10
            }while number > 0
            return output;
        }
        print(strings)
    

    パケット は、 び されるたびにoutputという を して されます. の を し、digitNames を してマッピングされた を します.この パケットは、 の の の を するために することができる.
    クローズド・パッケージ:1.パラメータがなければ、 り がなければ、inとinの のものは することができる. パケットが の のパラメータである は、()の に く-- パケット3に く. パケットパラメータが1つしかない は、()を してもよい-- パケットに く
    **3、 の い **
  • (1)2つのクラス の CustomViewクラス のコード:
  • class CustomView: UIView {
    // btnClickBlock,type
    // :()->() , ,
    var btnClickBlock:(()->())?
    // init(frame: CGRect)
    override init(frame: CGRect) {
    super.init(frame:frame)
    //
    let btn = UIButton(frame: CGRect(x: 15, y: 15, width: 80, height: 32))
    btn.setTitle(" ", for: .normal)
    btn.backgroundColor = UIColor.blue
    //
    btn.addTarget(self, action: #selector(CustomView.btnClick), for: .touchDown)
    //
    addSubview(btn)
    }
    //
    func btnClick(){
    if self.btnClickBlock != nil {
    //
    // : btnClickBlock ,
    self.btnClickBlock!()
    }
    }
    required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
    }
    }
    Controllerクラス のコード:class ViewController:UIViewController{
    override func viewDidLoad() {
        super.viewDidLoad()
    
        //  CustomView  
        let cutomeView = CustomView(frame: CGRect(x: 50, y: 50, width: 200, height: 200));
        // cutomeView btnClickBlock      
        cutomeView.btnClickBlock = {
           // () in        
            //              
            print("     ");
        }
        cutomeView.backgroundColor = UIColor.yellow;
        //      view 
        self.view.addSubview(cutomeView)}}
    
  • (2) コールバック//ネットワーク
      // - parameter urlString:         String
      // - parameter succeed:              
      // - parameter failure:              
      
      func requestData(url:String, success:@escaping ((Any?)->(Void)), failure:((Any?)->(Void))?)  {
          //      
          let session = URLSession.shared;
          let request = URLRequest(url: URL(string:url)!)
          let task = session.dataTask(with: request) { (data, respon, error) in
              if error == nil {
                  //    ,       ,        
                  success(data);
              }else{
                  //    ,       ,        
                  failure?(error);
              }
          }
          task.resume();
      }
      
      //    requestData  
      requestData(url: "http://www.baidu.com", success: { (data) -> (Void) in
          print("    ")
      }) { (error) -> (Void) in
          print("    ")
      }
    

  • **4、 の **
  • シナリオ1:weak weak var weakSelf=self// び し requestData requestData(url:"http://www.baidu.com「,success:{(data)->(Void)in print(" ")weakSelf?.view.backgroundColor=UIcolor.blue}){(error)->(Void)in print(" ")}
  • シナリオ2:シナリオと じタイプで、 く がもっと で、 パッケージに くことができ、 パッケージで されるselfはすべて requestData(url:"http://www.baidu.com「,success:{weak self->(Void)in self?.view.backgroundColor=UIcolor.red print(" ")}){(error)->(Void)in print(" ")}
  • シナリオ3:キーワードunownedを して、 から えばunownedはOCのunsafeに ています.unretained,//unownedは、 の オブジェクトが されても、 されたオブジェクトに する「 な」 は され、Optional ではなくnil requestData(url:」http://www.baidu.com「,success:{unowned self->(Void)in self.view.backgroundColor=UIcolor.red print(" ")}){(error)->(Void)in print(" ")}
  •     /*
    

    **5、 **
    パケットがパラメータとして に されると、 に の コールバックに されることがわかります. パケットは タスクが してから び されますが、 はすぐに され、 されるので、 でコールバックするために パケットは げる があります. パケットは、ネットワーク の したコールバックや したコールバックなどの のコールバックに に される. : の パッケージ パラメータにキーワード“@escaping”を します.キーワード「@escaping」は ていませんが、 したコールバックや したコールバックを き すことができます.タイプは“((Any?)->(Void))?”で、 ろに「?」が いています.これはクローズオプションタイプで、クローズタイプではないので、キーワード'@escaping'は ありません. と のコールバックを パッケージタイプにし、 で する は、パラメータの にキーワードを けます.*/
        func requestDataA(urlString:String,succeed: @escaping (Any?)->(Void),failure:@escaping (Any?)->(Void)){
            
            let request = URLRequest(url: URL(string: urlString)!);
            
            //      
            NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue()) { (_, data, error) in
                if error == nil {
                    //    ,       ,        
                    succeed(data);
                }else{
                    //    ,       ,        
                    failure(error);
                }
            }
        }