Swift超基礎(chǔ)語法(閉包篇)

"閉包,Swift中的新概念,然而除了寫法不同,實(shí)際上用法與用途都和OC中的Block沒什么不同"

閉包

Swift中并沒有block的概念,但為了取代block,Swift中提出了另一個(gè)概念"閉包"(我猜它的英文名應(yīng)該叫B-Box吧...童言無忌~)

Tips:
閉包經(jīng)常用于回調(diào),本質(zhì)也是一個(gè)代碼塊

閉包的使用方法:

  • 閉包的寫法:
    • 對(duì)比OC中的block,我們知道閉包的完整用法有三步:
1.閉包的定義:
    var 閉包名:(形參列表)->(返回值)
2.閉包的實(shí)現(xiàn):
    閉包名 = {
        (形參) -> 返回值類型 in
        // 執(zhí)行代碼
    }
3.閉包的回調(diào):
    閉包名(形參)
  • 我們?cè)谶@里模擬一個(gè)場(chǎng)景:創(chuàng)建一個(gè)網(wǎng)絡(luò)請(qǐng)求工具類,在子線程中請(qǐng)求數(shù)據(jù),在主線程中刷新UI,以此為例子來看一下閉包的使用方法
例:模擬網(wǎng)絡(luò)請(qǐng)求工具類
//創(chuàng)建網(wǎng)絡(luò)請(qǐng)求工具類
class HttpTool {
    func loadData(completeHandle : () -> ()) {  //1.第一步:定義發(fā)送網(wǎng)絡(luò)請(qǐng)求的方法,傳入一個(gè)"請(qǐng)求完成后回調(diào)的閉包"(這一步相當(dāng)于定義了一個(gè)() -> ()類型的閉包)
        dispatch_async(dispatch_get_global_queue(0, 0)) {   //跳轉(zhuǎn)到子線程
            print("請(qǐng)求數(shù)據(jù) -> \(NSThread.currentThread())")  //模擬發(fā)送網(wǎng)絡(luò)請(qǐng)求,同時(shí)打印當(dāng)前所在線程
            dispatch_sync(dispatch_get_main_queue(), {  //跳轉(zhuǎn)到主線程
                completeHandle()  //3.第三步:在主線程執(zhí)行回調(diào)
            })
        }
    }
}
//外部調(diào)用
        let tool = HttpTool()
        tool.loadData({() -> (Void) in  //2.第二步:實(shí)現(xiàn)閉包中的方法
            print("刷新UI -> \(NSThread.currentThread())")
        })
//打印結(jié)果
請(qǐng)求數(shù)據(jù) -> <NSThread: 0x7fe162c26a40>{number = 2, name = (null)}
刷新UI -> <NSThread: 0x7fe162d01730>{number = 1, name = main}
  • 閉包實(shí)現(xiàn)的簡(jiǎn)便寫法
    如果閉包沒有返回值沒有參數(shù),那么可以省略掉:"() -> () in",那么上面例子中的"外部調(diào)用"部分可以簡(jiǎn)寫為如下:
        let tool = HttpTool()
        tool.loadData({  //省略掉了() -> (Void) in
            print("刷新UI -> \(NSThread.currentThread())")
        })
  • 閉包的超簡(jiǎn)便寫法(尾隨閉包):
    尾行尾隨閉包顧名思義,當(dāng)我們的閉包是整個(gè)函數(shù)中的最后一個(gè)參數(shù)的時(shí)候可以把整個(gè)閉包(整個(gè)大括{}號(hào)中的部分)拿出來放到()后面,那我們繼續(xù)簡(jiǎn)化例子中"外部調(diào)用"的部分
        tool.loadData(){  //注意:此時(shí)閉包作為函數(shù)的最后一個(gè)參數(shù),被拿到了參數(shù)列表外部,并且緊跟在()后面
            print("刷新UI -> \(NSThread.currentThread())")
        }

尾隨閉包的進(jìn)一步簡(jiǎn)化:當(dāng)函數(shù)中只有一個(gè)參數(shù)的時(shí)候,并且恰好這個(gè)參數(shù)是閉包的時(shí)候,小括號(hào)()可以不寫!在追求極簡(jiǎn)的Swift語言中,這種最簡(jiǎn)化的閉包寫法,無疑是apple大力推薦的,如下:

        let tool = HttpTool()
        tool.loadData{  //注意:函數(shù)的參數(shù)列表()也可以不寫了哦
            print("刷新UI -> \(NSThread.currentThread())")
        }

Swift中快速解決閉包引發(fā)的循環(huán)引用:

  • block引發(fā)的循環(huán)引用
    block會(huì)對(duì)內(nèi)部的對(duì)象進(jìn)行強(qiáng)引用,我們拿當(dāng)前控制器的self來舉例:
    • 當(dāng)前控制器中定義一個(gè)httpTool類型的屬性tool,并將其實(shí)例化,則控制器強(qiáng)引用了tool
self.tool = HttpTool()  //self強(qiáng)引用tool
  • 如果tool中定義閉包屬性,則tool強(qiáng)引用該閉包
class HttpTool {
    var completeHandle : (() -> ())?
    func changeViewColor() -> Void {
        completeHandle!()
    }
}
  • 如果閉包內(nèi)部調(diào)用了self的某一些方法,則閉包強(qiáng)引用了self,
        self.tool!.completeHandle = {
            self.view.backgroundColor = UIColor.redColor()
        }

以上造成了循環(huán)引用

  • 解決循環(huán)引用的辦法:
    • weakSelf
      在OC中,我們常常定義一個(gè)變量來弱引用self,以此來代替self在閉包中使用
        self.tool = HttpTool()
        weak var wSelf = self //這里的wSelf是一個(gè)可選類型,因?yàn)閟elf被釋放后為nil,所以wSelf有可能指向nil
        self.tool!.completeHandle = {
            wSelf!.view.backgroundColor = UIColor.redColor()
        }
        self.tool?.changeViewColor()
  • [weak self]
    Swift中特有的方法,這種寫法會(huì)讓閉包內(nèi)所有的self都變?yōu)槿跻?/li>
        self.tool = HttpTool()
        self.tool!.completeHandle = {[weak self]() -> () in
            self!.view.backgroundColor = UIColor.redColor()  //這里的self為可選類型,有可能指向空(當(dāng)其引用的控制器被釋放時(shí),改變指向?yàn)閚il)
        }
        self.tool?.changeViewColor()
  • [unowned self]
    Swift中特有的方法,這種寫法會(huì)讓閉包內(nèi)所有的self都變?yōu)槿跻?與[weak self]不同的是,unowned引用的self所指向的實(shí)例被銷毀后,仍然會(huì)指向原有的存儲(chǔ)空間,所以這時(shí)閉包里的self既不是optional類型,也不可以指向nil
        self.tool = HttpTool()
        self.tool!.completeHandle = {[unowned self]() -> () in
            self.view.backgroundColor = UIColor.redColor()  //這里的self不是可選類型,故不需要強(qiáng)制解包
        }
        self.tool?.changeViewColor()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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