Swift 入門技術 - 閉包

cf8ein2l8e 9年前發布 | 5K 次閱讀 閉包 Swift Apple Swift開發

swift 中的閉包類似于 OC 中的 Block,但是使用比 Block 更廣泛

閉包的簡單說明

  1. 保存提前準備好的代碼
  2. 在需要的時候執行
  3. 可以當做參數傳遞
  4. 在 OC 中 Block 是匿名的函數
  5. 在 Swift 中閉包是特殊的函數

閉包的使用場景

  1. 異步執行完成回調
  2. 控制器間回調
  3. 自定義視圖回調
  4. 回調的特點
    • 以參數回調處理結果
    • 返回值為 Void

閉包的簡單使用

  1. 無參數無返回值

    //最簡單的閉包(無返回值無參數)
     // ( ) -> ( )
     let bibao1 = {
         print("hello, world")
     }
     //調用閉包
     bibao1()
  2. 有參數無返回值

    • 在閉包中,參數、返回值、實現代碼都可以寫在 { } 中
    • 使用一個關鍵字 in 分割定義和實現
    • { 形參列表 -> 返回值類型 in //實現代碼 }

      //帶參數無返回值的閉包
      // ( Int ) -> ( )
      let bibao2 = {
        (x: Int) -> () in
      
        print(x)
      }
      bibao2(10)
  3. 有參數有返回值

    //帶參數帶返回值的閉包
     // (Int) -> Int
     let bibao3 = {
         (x: Int) -> Int in
    
         return x + 10
     }
     print(bibao3(10))

閉包作為參數傳遞

  • 閉包和 Block 一樣可以作為參數進行傳遞

    //閉包作為參數傳遞
      // (Int, Int) -> Int
      let bibao4 = {
          (x: Int, y: Int) -> Int in
    
          return x + y
      }
    
      func test(x: Int, y: Int, bibao: (Int, Int) -> Int) {
          bibao(x, y)
      }
      test(x: 10, y: 20, bibao: bibao4)

尾隨閉包

  • 如果函數的最后一個參數是閉包,函數參數可以提前結束,最后的一個參數使用 { } 來包裝閉包的代碼
  • 使用尾隨閉包對上述的參數傳遞代碼進行調整,可以使用以下方式進行修改

    //尾隨閉包
      func test(x: Int, y: Int, bibao: (Int, Int) -> Int) {
          bibao(x, y)
      }
    
      test(x: 10, y: 20) {
          (x, y) -> Int in
    
          return x + y
      }

逃逸閉包

  • 在 Swift 中 閉包默認是非逃逸的,不能被其他對象引用
  • @escaping 修飾的就是逃逸閉包,可以被其他對象引用

    func test(a: Int, aa: ()->()) {
          aa()
      }
    
      func getData(result: @escaping ([String]) -> ()) {
    
          test(a: 10, aa: {
              result(["1", "2"])
          })
      }

閉包的循環引用

  • 由于 { } 的作用域,在使用閉包的同時要注意循環引用的問題
  • 在 OC 中可以使用 weak 和 unsafe_unretained 兩種方式
  • 在 Swift 中主要使用 weak 和 unowned 兩種方式來解決

    1. weak

      • Swift 中推薦使用的方法
      • 需要注意解包問題
      • 修飾的 self 都是弱引用
      class Person {
        var num: Int = 0
        var bb: (() -> ())?
      
        // weak 方式一
        func test1() {
            weak var weakSelf = self
            bb = {
                print("test1", weakSelf!)
                let pr = weakSelf?.num
                pr! + 10
            }
            bb!()
        }
      
        // weak 方式二
        func test2() {
            bb = {
                //標識,在這個閉包里使用的所有 self 都是弱引用
                [weak self]
                () -> () in
      
                print(self!)
                print(self!)
            }
            bb!()
        }
      }
    2. unowned

      • 修飾的 self 都是 assign 的,不會強引用
      • 如果對象釋放,指針地址不會變化
      • 若被釋放之后繼續調用,會出現野指針問題
      class Person {
         var num: Int = 0
         var bb: (() -> ())?
      
         // unowned 方式一
         func test1() {
             unowned let weakSelf = self
             bb = {
                 print("test1", weakSelf)
                 let pr = weakSelf.num
                 pr + 10
             }
             bb!()
         }
      
         // unowned 方式二
         func test2() {
             bb = {
                 //標識,在這個閉包里使用的所有 self 都是弱引用
                 [unowned self]
                 () -> () in
      
                 print(self)
                 print(self)
             }
             bb!()
         }
      }

 

來自:http://www.jianshu.com/p/880e9e6d99d7

 

 本文由用戶 cf8ein2l8e 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!