iOS Block 語法及底層實(shí)現(xiàn)

前言

? ? ? ? iOS開發(fā)的同學(xué)們肯定都用過block,對block 的運(yùn)用熟練在我們開發(fā)過程中很有必要创夜;在此我也對其進(jìn)行一番解讀查吊,希望能在大家開發(fā)或者面試過程中有所幫助。

一叉瘩、block 概要

1、什么是block

一句話:帶有自動變量(局部變量)的匿名函數(shù)粘捎。?

Q1 什么 是匿名函數(shù) ?度娘解釋曰?;

Q2 自動變量相關(guān):C語言函數(shù)中可能用到的變量由自動變量薇缅、函數(shù)參數(shù)、靜態(tài)變量攒磨、靜態(tài)全局變量泳桦、全局變量;有興趣的還可以去探究其內(nèi)存中的存儲域

二咧纠、block用法定義

1蓬痒、block語法及變量

block 語法: ^ 返回值類型 參數(shù)列表 表達(dá)式?

^ (NSString *) (NSString *bookId){}

省略返回值寫法:

^(void){};

省略返回值及參數(shù)寫法:

^{};

2、block 實(shí)質(zhì)

簡單些一行block

聲明一個block并打印

?void(^block)(void)=^{

? ? ? ? printf("block block \n");

? ? };

? ? block();

通過在終端命令行 clang -rewrite-objc 源代碼文件名 漆羔,會生成相應(yīng)的.cpp文件梧奢,由C++編寫的源文件。具體實(shí)現(xiàn)大家可以自己去操作一下我這里貼出一段類似代碼:

C++ 源碼文件中很多內(nèi)容演痒,只要看到截圖的調(diào)用部分亲轨。

block實(shí)質(zhì)也是一個oc對象,簡單來說和class代碼的設(shè)計思想是為其構(gòu)建一個結(jié)構(gòu)體struct鸟顺,把結(jié)構(gòu)體相應(yīng)參數(shù)做索引惦蚊,遵循一定的規(guī)則,去找到相應(yīng)的實(shí)現(xiàn)方法讯嫂;同樣的我們在設(shè)計OC 對象時也應(yīng)借助這個思想蹦锋。無論對象怎么變化,他有一個基本的結(jié)構(gòu)體單元欧芽。

三莉掂、block截獲自動變量

1、block底層如何截獲自動變量值

上文中講到block實(shí)際是一個oc 對象千扔,它就有isa指針憎妙、變量等對象屬性库正,當(dāng)執(zhí)行block語句中有使用外部變量時,會將相應(yīng)的變量值 自動聲明并存儲到block 的結(jié)構(gòu)體當(dāng)中去

2厘唾、blcok 捕獲自動變量

__block 修飾詞修飾變量褥符,類似于static、auto 等c語言聲明詞抚垃,一經(jīng)修飾喷楣,底層會做相應(yīng)的處理;至于做了什么讯柔,要跟blcok 存儲域有關(guān)抡蛙。blcok類型 有三種?

棧上 NSConcreteStackBlock

堆上 NSConcreteMallocBlock

全局 NSConcreteGlobalBlock (存儲在程序的數(shù)據(jù)區(qū))

當(dāng)使用的是棧上的block 時护昧,你使用的又是局部變量魂迄,想截獲變量改變其值,必須用__block 修飾惋耙,是將該變量變?yōu)橐粋€結(jié)構(gòu)體自動變量才能被修改捣炬,示例如下:

block_t=blk;

{

__block NSMutableArray *array=[[NSMutableArray alloc] init];

blk=^(NSObject obj){

? ? [array add object:obj];

}

blk([[NSObject alloc] init]);

}

或者這么寫:

block_t=blk;

{

?NSMutableArray *array=[[NSMutableArray alloc] init];

blk=[^(NSObject obj){

[array add object:obj];

} copy]

blk([[NSObject alloc] init]);

}

這兩種寫法 都是 將變量array 從 棧copy 到 堆上,第一種是array 變量通過 block 修飾符生成一個forwarding指針绽榛,指向其拷貝到堆上的生成的自動變量結(jié)構(gòu)體湿酸;第二種是把block 拷貝到堆上截獲的變量也會被拷貝到堆上,這樣當(dāng)運(yùn)行完大括號的代碼時灭美,array 也不會被釋放推溃,知道block 運(yùn)行完成被釋放時,array 才會跟著被釋放釋放是由系統(tǒng)調(diào)用dispose完成届腐。

關(guān)于對象類型自動變量捕獲铁坎,使用方法一還是方法二有個小總結(jié):

1)block作為函數(shù)返回值返回時

2)將block賦值給類的附有__strong 修飾符的id 類型或block類型成員變量時

3)向方法名中含有usingBlock 的cocoa框架方法或GCD 的api 傳遞block 時;

除了以上幾種情況外犁苏,其他都建議使用方法二硬萍。

由于以上變量都是 strong 類型變量,如果是weak 類型變量呢围详?類似如下:

block_t=blk;

{

__block NSMutableArray __weak *array=[[NSMutableArray alloc] init];

blk=^(NSObject obj){

? ? [array add object:obj];

}

blk([[NSObject alloc] init]);

}

經(jīng)驗(yàn)證朴乖,運(yùn)行完代碼,在作用域外array 會被釋放助赞,array 不會有任何改變买羞。

3、blcok循環(huán)引用

block 的循環(huán)引用是我們平時寫代碼經(jīng)常要注意的問題雹食,循環(huán)引用的原因即為 block 強(qiáng)持有該 自動變量畜普,自動變量又強(qiáng)持有 blcok,運(yùn)行完后釋放時你等待我釋放婉徘,我等待你釋放漠嵌,由此造成死循環(huán)咐汞;類似的有多線程中的死鎖問題,二等待一運(yùn)行完一等待二運(yùn)行完導(dǎo)致兩者都在等待執(zhí)行卡死在那兒儒鹿。如下圖

循環(huán)引用示意圖

避免循環(huán)引用的方式主要是兩種:

1)使用__weak 或 __unsafe_unretained修飾自動變量使得blcok 弱持有 自動變量化撕,當(dāng)block 執(zhí)行完后,blcok 和對象都能被釋放

2)使用__block 修飾自動變量 约炎, 但是 必須要調(diào)用 一次 block 植阴,才能使得 block變量對 自動變量的持有釋放,不然還是會有循環(huán)引用

4圾浅、blcok 拷貝/釋放

有一個小點(diǎn)掠手,顯示調(diào)用copy 和release 的情況,是在非ARC 情況下即需要我們主動去調(diào)用release 方法 將copy 到堆里的block 釋放掉狸捕,這里我不做詳細(xì)描述喷鸽,有興趣的可以自己去度娘問問;

block 的使用博大精深灸拍,需要更進(jìn)一步的探尋它的使用場景做祝,期待與你一起深入學(xué)習(xí)研究。鸡岗。混槐。

參考:

1、<<Object-C 高級編程iOS 與OSX 多線程和內(nèi)存管理>>

2轩性、http://www.reibang.com/p/6a7c498c42bc

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末声登,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子揣苏,更是在濱河造成了極大的恐慌悯嗓,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舒岸,死亡現(xiàn)場離奇詭異绅作,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蛾派,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門俄认,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洪乍,你說我怎么就攤上這事眯杏。” “怎么了壳澳?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵岂贩,是天一觀的道長。 經(jīng)常有香客問我巷波,道長萎津,這世上最難降的妖魔是什么卸伞? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮锉屈,結(jié)果婚禮上荤傲,老公的妹妹穿的比我還像新娘。我一直安慰自己颈渊,他們只是感情好遂黍,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俊嗽,像睡著了一般雾家。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绍豁,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天芯咧,我揣著相機(jī)與錄音,去河邊找鬼妹田。 笑死唬党,一個胖子當(dāng)著我的面吹牛鹃共,可吹牛的內(nèi)容都是我干的鬼佣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼霜浴,長吁一口氣:“原來是場噩夢啊……” “哼晶衷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起阴孟,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤晌纫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后永丝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锹漱,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年慕嚷,在試婚紗的時候發(fā)現(xiàn)自己被綠了哥牍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡喝检,死狀恐怖嗅辣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挠说,我是刑警寧澤澡谭,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站损俭,受9級特大地震影響蛙奖,放射性物質(zhì)發(fā)生泄漏潘酗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一雁仲、第九天 我趴在偏房一處隱蔽的房頂上張望崎脉。 院中可真熱鬧,春花似錦伯顶、人聲如沸囚灼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灶体。三九已至,卻和暖如春掐暮,著一層夾襖步出監(jiān)牢的瞬間蝎抽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工路克, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留樟结,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓精算,卻偏偏與公主長得像瓢宦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子灰羽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評論 2 348