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

"閉包,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語(yǔ)言中,這種最簡(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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市狂芋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖鸳劳,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蘑险,死亡現(xiàn)場(chǎng)離奇詭異冠摄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)毁兆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阴挣,“玉大人气堕,你說我怎么就攤上這事⊥偷酰” “怎么了送巡?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)盒卸。 經(jīng)常有香客問我骗爆,道長(zhǎng),這世上最難降的妖魔是什么蔽介? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任摘投,我火速辦了婚禮煮寡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘犀呼。我一直安慰自己幸撕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布外臂。 她就那樣靜靜地躺著坐儿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宋光。 梳的紋絲不亂的頭發(fā)上貌矿,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音罪佳,去河邊找鬼逛漫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赘艳,可吹牛的內(nèi)容都是我干的酌毡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蕾管,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼枷踏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起娇掏,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤呕寝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后婴梧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體下梢,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年塞蹭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了孽江。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡番电,死狀恐怖岗屏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漱办,我是刑警寧澤这刷,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站娩井,受9級(jí)特大地震影響暇屋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜洞辣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一咐刨、第九天 我趴在偏房一處隱蔽的房頂上張望昙衅。 院中可真熱鬧,春花似錦定鸟、人聲如沸而涉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)啼县。三九已至,卻和暖如春躯泰,著一層夾襖步出監(jiān)牢的瞬間谭羔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工麦向, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人客叉。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓诵竭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親兼搏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卵慰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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