swift學習筆記 --- Closures

一.閉包創建語法

       {(parameters) -> return type in

         statements

  }

 例子 :

          let names = ["Chris","Alex","Ewa","Barry","Daniella"]

    func backward( s1: String,_ s2: String) ->Bool {

          return s1 > s2

    }

    var reversedNames = names.sort(backward)

    上面的是傳入普通函數,我們也可以傳入一個閉包

    reversedNames = names.sort({ (s1:String, s2: String) -> Boolin

    return s1 > s2

    })

二.閉包類型推斷

     閉包被當做參數傳入方法時,閉包的參數類型和返回值有可能被推斷出來,這時我們可以省略參數類型和返回值,        因此上面的      例子也可以寫成:

      reversedNames =names.sort({ s1, s2 inreturn s1 > s2 } )

      如果閉包裏只有一條可執行語句,swift 是可以推斷出返回值的,因此return 語句可以省略(前提是編譯器知道必定有返回值)

       reversedNames = names.sort({ s1, s2 in s1 > s2 } )

二.簡短的參數名

     如果我們知道函數的類型,既我們可以從函數裏知道,傳入函數的閉包需要幾個參數每個參數的類型是什麼,我們       可以省略閉      包的參數列表,in 關鍵詞也可省略,因爲此時閉包裏全爲可執行語句。通過$0,$1,$2......的方式來引用傳      入的參數

    reversedNames =names.sorted(by: { $0 > $1 } )

三. Trailing Closures

    如果閉包是函數的最後一個參數我們可以把閉包寫在函數調用的外邊
    如: 
         reversedNames = names.sort() { $0 > $1 }
     如果函數只有閉包一個參數我們可以省略()

    reversedNames = names.sort { $0 > $1 }


四.捕獲值

     閉包可以捕獲在閉包外面內容常量和變量,閉包可以引用和改變這些常量和變量。閉包的捕獲使這些變量和常量不        被釋放。

     func makeIncrementer(forIncrement amount: Int) -> () -> Int {

       var runningTotal = 0

       func incrementer() -> Int {

         runningTotal += amount

         return runningTotal

       }

      return incrementer

   }

   let incrementByTen = makeIncrementer(forIncrement: 10)

   incrementByTen()

   // returns a value of 10

   incrementByTen()

   // returns a value of 20

   incrementByTen()


五.閉包是引用類型

   當您將一個函數或一個閉包賦給一個常量或一個變量時,您實際上是在設置常量或變量來引用函數或閉包的函數。

六.閉包的Non-Escaping和 Escaping

   Non-Escaping Closures


      

     注意閉包沒有從這函數體內逃逸。當函數結束,傳入的閉包從函數體出來時,沒有添加額外的引用。閉包的引用計數在函數開始執行和結束是相同的

   Escaping Closures

          
          逃逸閉包的引用計數在函數體內增加,導致函數開始執行和執行之後引用計數不想同。
          

   Escaping and Non-Escaping in Swift 3

          1.在 swift3閉包參數被默認爲非逃逸,如果你想使閉包逃逸,你必須加上@escaping屬性
          如果閉包是非逃逸的,編譯器會做一些優化
          2.
            

    var completionHandlers: [() -> Void] = []

    func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {

    completionHandlers.append(completionHandler)

    }



    func someFunctionWithNonescapingClosure(closure: () -> Void) {

      closure()

    }


    class SomeClass {

       var x = 10

       func doSomething() {

        someFunctionWithEscapingClosure { self.x = 100 }

        someFunctionWithNonescapingClosure { x = 200 }

       }

   }


   let instance = SomeClass()

   instance.doSomething() 

   print(instance.x)

   // Prints "200"


  completionHandlers.first?()

  print(instance.x)

  // Prints "100"

  在逃逸閉包裏必須用 self 來引用外圍的內容,而非逃逸閉包則不用。



七.自動閉包

   一個自動閉包是一個沒有參數,包裹一個表達式的閉包。當我們調用這個閉包它返回這個表達式的值。

    var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

  print(customersInLine.count)

  // Prints "5"


  let customerProvider = { "ddd";}

  print(customersInLine.count)

  // Prints "5"


  print("Now serving \(customerProvider())!")

  // Prints "Now serving Chris!"

  print(customersInLine.count)

  // Prints "4"


         

     


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章