13.閉包(特殊的函數(shù))

  • 1.閉包的介紹

    • 閉包和OC中的block非常相似
      • OC中的block是匿名的函數(shù)
      • Swift中的閉包是一個(gè)特殊的函數(shù)
      • block和閉包都經(jīng)常用于回調(diào)
    • 注意:閉包和block一樣,第一次使用時(shí)可能不習(xí)慣它的語法,可以先按照使用簡單的閉包,隨著學(xué)習(xí)的深入,慢慢掌握其靈活的運(yùn)用方法.
  • 2.閉包的使用

    • 1.先回顧一下block的使用

      @property(nonatomic,strong) void(^myblock)();
      // block 的格式: 返回值類型(^block名稱) (參數(shù)列表)
      self.myblock = ^(){
      
              NSLog(@"block的打印");
      
       };
      self.myblock();
      
    • 2.閉包的基本介紹
      /*
      * 閉包和oc中的block非常相似
      * oc中的block類似于匿名函數(shù)
      * 閉包是用來定義函數(shù)
      * 作用: block 是用于保存一段代碼,在需要的時(shí)候執(zhí)行
      * 閉包也是用于保存一段代碼,在需要的時(shí)候執(zhí)行
      * 做一個(gè)耗時(shí)的操作
      */

      /*
       * 閉包的基本格式:
         in的含義是用來區(qū)分形參返回值和要執(zhí)行的代碼
       *  {
            (形參列表) -> (返回值)
             in
             需要執(zhí)行的代碼
          }
       *
       */
        loadData {
          
          print("回調(diào)")
      }
      
      func loadData(request:()->()){
      
          print("執(zhí)行耗時(shí)操作")
          request()
      
      }
      
  • 3.閉包的幾種格式

    • 1.將閉包通過實(shí)參傳遞給函數(shù)

      loadData (request: { 
         
          print("回調(diào)")
       })
       func loadData(request:()->()){
      
          print("執(zhí)行耗時(shí)操作")
          request()
      
       }
      
  • 2.如果閉包是函數(shù)的最后一個(gè)參數(shù),那么閉包可以寫在函數(shù)()的后面
    loadData() {

          print("回調(diào)2")
         
     }
     func loadData(request:()->()){
    
         print("執(zhí)行耗時(shí)操作")
         request()
    
     }
    
  • 3.如果函數(shù)只接受一個(gè)參數(shù),并且這個(gè)參數(shù)是閉包,那么()可以省略
    loadData {

         print("回調(diào)2")
        
    }
    
    func loadData(request:()->()){
    
         print("執(zhí)行耗時(shí)操作")
         request()
    
    }
    
  • 4.閉包的返回值和參數(shù)

/*
 *  兩個(gè)閉包  創(chuàng)建一個(gè) UIscrollview 上添加button
 *
 *
 */
let sc1 = createScrollview(buttonCount: { () -> Int in
    
    return 15
}) { (index) -> UIView in
    
    let width1 = 80
    let button = UIButton()
    button.backgroundColor = UIColor.red
    button.frame = CGRect(x:index*width1,y:10,width:width1,height:80)
    button.setTitle("標(biāo)題\(index)", for: UIControlState(rawValue: 0))
    return button
    
    }
    
view.addSubview(sc1)
    
    /*
     * 要求定義一個(gè)方法來創(chuàng)建UIScrollView,
     * 1.并且上面有多個(gè)按鈕,必須通過閉包來告訴該方法
     * 2.并且如何創(chuàng)建按鈕也需要閉包來創(chuàng)建
     */
   
    // 5.將scrollview添加到控制器的view上
    // 特點(diǎn): 沒有寫self
    // swift推薦:能不寫self就不寫self

    func createScrollview(buttonCount:()->Int,buttonIndex1: (_ num:Int)->UIView) -> UIScrollView {
    
    // 數(shù)組的數(shù)量
    let count = buttonCount()
    
    // 1.創(chuàng)建scrollview
    let sc = UIScrollView(frame: CGRect(x:0,y:64,width:414,height:100))
    sc.backgroundColor = UIColor.blue
    view.addSubview(sc)
    
    // 2.在scrollview上放置button
    
    for i in 0..<count {
        
        /*
        let button = UIButton()
        button.backgroundColor = UIColor.red
        button.frame = CGRect(x:i*width1,y:10,width:width1,height:80)
        button.setTitle("標(biāo)題\(i)", for: UIControlState(rawValue: 0))
        sc.addSubview(button)
        */
        
        let button = buttonIndex1(i)
        sc.contentSize = CGSize(width:CGFloat(count) * button.bounds.width,height:100)
        sc.addSubview(button)
        
    }
    
    return sc
}
  • 5.循環(huán)引用

     import UIKit
    
    class ViewController: UIViewController {
    
     /*
      * 在swift中,如果在某個(gè)類中定義一個(gè)屬性,那么這個(gè)屬性必須要初始化,否則就會(huì)報(bào)錯(cuò)
      * 如果暫時(shí)不想初始化,那么可以在后面寫上一個(gè) ? 也就是可選類型
      */
    
      // 注意:這個(gè)是錯(cuò)誤的寫法,當(dāng)前寫法代表閉包的返回值可以是nil
      //var finsh: ()->()?
      // 下面是正確的寫法
      var finsh: (()->())?
     
      override func viewDidLoad() {
      super.viewDidLoad()
     
      weak var weakSelf = self
      loadata { 
          
          print("回調(diào)")
          // 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self
          // 所以以后看到self基本上都是和閉包有關(guān)系
          weakSelf!.view.backgroundColor = UIColor.brown
            
          }
      
      }
    
      func loadata(finsh:()->())  {
      
      print("執(zhí)行耗時(shí)操作")
      finsh()
      
      }
    
      override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
     }
    
    }
    

**循環(huán)引用解決:以上面的為例

方式一:
- 使用weak,對(duì)當(dāng)前控制器使用弱引用
- 但是因?yàn)閟elf可能有值也可能沒有值,因此weakSelf是一個(gè)可選類型,在真正使用時(shí)可以對(duì)其強(qiáng)制解包(該處強(qiáng)制解包沒有問題,因?yàn)榭刂破饕欢ù嬖?否則無法調(diào)用所在函數(shù))
weak var weakSelf = self
loadata {

       print("回調(diào)")
       // 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self
       // 所以以后看到self基本上都是和閉包有關(guān)系
        weakSelf!.view.backgroundColor = UIColor.brown

        }
      }

方式二:
- 和方案一類型,只是書寫方式更加簡單
- 可以寫在閉包中,并且在閉包中用到的self都是弱引用
loadata { [weak self] () -> () in

            print("回調(diào)")
            // 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self
            // 所以以后看到self基本上都是和閉包有關(guān)系
            self!.view.backgroundColor = UIColor.brown

            }
        }

方式三:
 -  使用關(guān)鍵字unowned
 - 從行為上來說 unowned 更像OC中的 unsafe_unretained
 - unowned 表示:即使它原來引用的對(duì)象被釋放了,仍然會(huì)保持對(duì)被已經(jīng)釋放了的對(duì)象的一個(gè) "無效的" 引用,它不能是 Optional 值,也不會(huì)被指向 nil

        loadata { [unowned self] () -> () in

            print("回調(diào)")
            // 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self
            // 所以以后看到self基本上都是和閉包有關(guān)系
            self.view.backgroundColor = UIColor.brown

          }
        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 介紹 Swift官方開發(fā)文檔對(duì)于閉包的介紹是這樣的:閉包是可以在代碼中被傳遞和引用的功能性獨(dú)立模塊。Swift 中...
    Latte_Bear閱讀 885評(píng)論 0 1
  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出,用來撰寫 OS X 和 iOS 應(yīng)用程序 ...
    大L君閱讀 3,301評(píng)論 3 25
  • 在上一篇文章Swift中的變量和常量中我總結(jié)了一些自己對(duì)于變量和常量的認(rèn)識(shí),最近學(xué)習(xí)了閉包,順便給大家分享一下關(guān)于...
    老板娘來盤一血閱讀 18,745評(píng)論 16 87
  • "閉包,Swift中的新概念,然而除了寫法不同,實(shí)際上用法與用途都和OC中的Block沒什么不同" 閉包 Swif...
    S_Lyu閱讀 609評(píng)論 0 15
  • 使用playground來測(cè)試代碼很有意思 Xcode 7.2 如果項(xiàng)目名稱包含中文和數(shù)字 在數(shù)組中添加元素 會(huì)造...
    一黑閱讀 605評(píng)論 0 0