定義
帶有局部變量的匿名函數(shù)恰响。
標(biāo)志
^
使用
跟函數(shù)很像:
1、可以保存代碼涌献;
2胚宦、可以有返回值;
3、可以有形參枢劝;
4井联、調(diào)用方式一樣;
存儲(chǔ)區(qū)域
三種存儲(chǔ)方式:棧您旁、全局烙常、堆。
優(yōu)點(diǎn)
幫助組織獨(dú)立的代碼段被冒,提高代碼的復(fù)用性和可讀性。
實(shí)現(xiàn)機(jī)制
方法回調(diào)轮蜕。
(所謂回調(diào)昨悼,是在某個(gè)事件發(fā)生前預(yù)先準(zhǔn)備好的一段代碼,相應(yīng)的事件一旦發(fā)生跃洛,系統(tǒng)就會(huì)執(zhí)行這段代碼率触。)
特性
捕獲變量。
概念
當(dāng)某個(gè)block對(duì)象訪問了一個(gè)在該block對(duì)象之前聲明的變量時(shí)汇竭,可以稱該block對(duì)象捕獲了這個(gè)變量葱蝗。一旦block對(duì)象捕獲了某個(gè)變量,該變量之后的變化就不會(huì)對(duì)捕獲后的變量產(chǎn)生任何影響细燎。
實(shí)質(zhì)
默認(rèn)情況下两曼,在block中訪問的外部變量是復(fù)制過去的,即:寫操作不對(duì)原變量生效玻驻。
原因
Apple這樣設(shè)計(jì)應(yīng)該是考慮到了block的特殊性悼凑,block也屬于“函數(shù)”的范疇,變量進(jìn)入block璧瞬,實(shí)際就是已經(jīng)改變了作用域户辫。在幾個(gè)作用域之間進(jìn)行切換時(shí),如果不加上這樣的限制嗤锉,變量的可維護(hù)性將大大降低渔欢。
如果需要修改外部變量,怎么實(shí)現(xiàn)
1瘟忱、修改變量為static全局變量奥额;
2、用__block關(guān)鍵字修飾變量访诱;
(__block關(guān)鍵字的底層實(shí)現(xiàn)原理:__block所起到的作用就是只要觀察到該變量被 block 所持有披坏,就將“外部變量”在棧中的內(nèi)存地址放到了堆中。進(jìn)而在block內(nèi)部會(huì)直接引用變量的地址盐数,所以也可以修改外部變量的值棒拂。)
循環(huán)引用問題
block創(chuàng)建前weak化
概念
? ? 在 block 內(nèi)如果需要訪問 self 的方法、變量,建議使用 weakSelf帚屉。
原因
? ? 創(chuàng)建block函數(shù)之前一般需要對(duì)self進(jìn)行weak化谜诫,否則會(huì)造成循環(huán)引用無法釋放,即內(nèi)存泄漏攻旦。
方法
__weak typeof(self) weakSelf = self;
ARC和MRC兩種情況下的weak化:
? ? 1. ARC:通過使用__weak聲明一個(gè)weakself來代替原來的self喻旷,已告訴block內(nèi)部不要對(duì)self進(jìn)行強(qiáng)引用。
? ? 2. MRC:解決方式與上述基本一致牢屋,只不過將__weak關(guān)鍵字換成__block即可且预。
block內(nèi)部需多次訪問要strong化
概念
? ? 如果在 block 內(nèi)需要多次訪問 self,則需要使用 strongSelf烙无。
原因
? ?保證代碼在執(zhí)行到block中锋谐,self不會(huì)被釋放,當(dāng)block執(zhí)行完后截酷,會(huì)自動(dòng)釋放該strongSelf涮拗。在多線程環(huán)境下(block中的weakSelf有可能被析構(gòu)的情況下),需要先將self轉(zhuǎn)為strong指針迂苛,避免在運(yùn)行到某個(gè)關(guān)鍵步驟時(shí)self對(duì)象被析構(gòu)三热。
方法
? __strong typeof(weakSelf) strongSelf = weakSelf; //內(nèi)部strong
經(jīng)典代碼
? weak–strong dance
? (以下代碼來自AFNetworking,堪稱使用weak–strong dance的經(jīng)典)
代碼分析
? ? 1. __weak __typeof(self)weakSelf = self:
? ? 為防止callback內(nèi)部對(duì)self強(qiáng)引用三幻,weak一下就漾。
? ? 2.__strong__typeof(weakSelf)strongSelf = weakSelf:
? ? 如果不轉(zhuǎn)成strongSelf而使用weakSelf,后面幾句話中念搬,有可能在第四句執(zhí)行之后self的對(duì)象可能被析構(gòu)掉从藤,然后后面的StausBlock沒有執(zhí)行,導(dǎo)致邏輯錯(cuò)誤锁蠕。
? ? 3. 使用block前對(duì)block判空夷野。
? ? 4. typeof 是一個(gè)一元運(yùn)算,放在一個(gè)運(yùn)算數(shù)之前荣倾,運(yùn)算數(shù)可以是任意類型悯搔。它返回值是一個(gè)字符串,該字符串說明運(yùn)算數(shù)的類型舌仍。即可以根據(jù)typeof()括號(hào)里面的變量妒貌,自動(dòng)識(shí)別變量類型并返回該類型。