Block學(xué)習(xí)筆記2-Block實(shí)質(zhì)

參考書籍:《Effective Objective-C 2.0》 《Objective-C高級編程 iOS與OS X多線程和內(nèi)存管理》
根據(jù)書中所說,Block是“帶有自動(dòng)變量值的匿名函數(shù)”喉酌,下面算是我的讀書筆記,附上由clang編譯出來的過程代碼來理解Block的實(shí)質(zhì)赐俗。
首先介紹下clang,Clang是一個(gè)[C語言]弊知、[Objective-C]阻逮、C++語言的輕量級編譯器。---百度百科

1.相關(guān)clang命令

可能用到的關(guān)于clang的指令如下:
cd到main目錄下吉捶,執(zhí)行clang -rewrite-objc main.m指令夺鲜,可以將OC源碼轉(zhuǎn)換成C語言源代碼,但要注意這里轉(zhuǎn)換出來的C源碼并不是最終程序執(zhí)行的源碼呐舔,只是過程代碼币励,所以僅便于我們從更加底層的了解OC源碼。源碼無錯(cuò)且執(zhí)行完畢后同級目錄下便會出現(xiàn)main.cpp文件珊拼。

1.若要指定模擬器環(huán)境下運(yùn)行:
首先可執(zhí)行xcodebuild -showsdks查看本地裝有的SDK
然后執(zhí)行xcrun -sdk iphonesimulatorx.x clang -rewrite-objc main.m(x.x即為本機(jī)安裝的模擬器版本)
2.若指定真機(jī)運(yùn)行
xcrun -sdk iphoneosx.x clang -rewrite-objc main.m
3.若代碼中import了第三方的SDK食呻,可以通過下列命令關(guān)閉
xcrun -sdk iphonesimulator10.0 clang -rewrite-objc -F /Users/Desktop main.m
注意,在mac系統(tǒng)下澎现,無需先建工程再執(zhí)行源碼轉(zhuǎn)化仅胞,在任意目錄先新建一個(gè)m文件即可轉(zhuǎn)換。

2.Block源碼

先舉一個(gè)簡單的block剑辫,方便查看Block的結(jié)構(gòu)干旧。

OC源碼:
#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
      @autoreleasepool {  
          void (^aBlock)() = ^{
                                  NSLog(@"Hello world !");
                               };
          aBlock();
      }  
    return 0;
}

轉(zhuǎn)換后的相關(guān)C源碼如下:(轉(zhuǎn)換出來的源碼雖然有九萬多行,但大部分是因?yàn)槲覍?dǎo)入了Foundation框架妹蔽,以下只列出與main有關(guān)的部分源碼)

Block c源碼截圖.png

雖然書中已經(jīng)寫的很詳細(xì)了椎眯,但我這里重新理一遍理解的思路挠将,一方面是便于自己梳理要點(diǎn)便于記憶,另一方面有關(guān)于書中有些疑問编整,在這里記下來舔稀,方便日后交流與回顧。
下面根據(jù)上圖中的標(biāo)號順序來理解這段轉(zhuǎn)換成C源碼的實(shí)現(xiàn)原理:
1.先來看看一眼就能認(rèn)出的block內(nèi)容部分掌测,在OC中添加的block內(nèi)容為^{NSLog(@"Hello world !");};在標(biāo)注1的地方正好能看到熟悉的NSLog内贮,所以可以看出靜態(tài)函數(shù)__main_block_func_0即對應(yīng)OC中block中執(zhí)行的函數(shù)部分。

2.接著來看main_block_func_0中傳遞的參數(shù)為 main_block_impl_0結(jié)構(gòu)體類型的 cself指針汞斧,這里cself就相當(dāng)于self(不做拓展介紹夜郁,更多的細(xì)節(jié)請自己查閱更加底層的資料)。然后來具體看__main_block_impl_0結(jié)構(gòu)體粘勒,在標(biāo)注2的地方即為這個(gè)結(jié)構(gòu)體的成員變量與構(gòu)造函數(shù)拂酣。
這個(gè)結(jié)構(gòu)體包含兩種變量與一個(gè)構(gòu)造函數(shù):

  • __block_impl impl
  • __main_block_desc_0* Desc;
  • 構(gòu)造函數(shù)__main_block_impl_0

前兩種結(jié)構(gòu)體變量稍后講述,先看一下構(gòu)造函數(shù)main_block_impl_0中所傳遞的參數(shù)為void *fp仲义,struct __main_block_desc_0 *desc, int flags=0
其中fp即為指向block要實(shí)現(xiàn)的函數(shù)指針剑勾,desc為block的相關(guān)描述信息埃撵,直接賦給Desc變量,最后是帶默認(rèn)值的flags變量虽另。

3.先來看__main_block_impl_0結(jié)構(gòu)體:

  • isa:指向?qū)嵗龑ο笤萘酰帽砻鰾lock也跟一般的OC對象類似,擁有isa指針捂刺,共有三種block類型:_NSConcreteStackBlock谣拣、_NSConcreteGlobalBlock、_NSConcreteMallocBlock
  • Flags :按位承載 block 的附加信息族展;
  • Reserved:保留變量森缠;
  • FuncPtr: 函數(shù)指針,指向 Block 要執(zhí)行的函數(shù)

4.再來看__main_block_desc_0:block 的相關(guān)描述信息結(jié)構(gòu)體

  • reserved:結(jié)構(gòu)體信息保留字段
  • Block_size:結(jié)構(gòu)體大小
  • 結(jié)構(gòu)體類型變量: __main_block_desc_0_DATA

5.main函數(shù)部分
void (*aBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
這句能猜到就對應(yīng)著void (^aBlock)() = ^{NSLog(@"Hello world !");};
將其強(qiáng)制轉(zhuǎn)化等操作去掉后仪缸,就僅剩下了*aBlock = &__main_block_impl_0;就可以看出這就是一個(gè)簡單的指針賦值贵涵,將main_block_impl_0結(jié)構(gòu)體賦值給aBlock指針。我的理解為通過構(gòu)造函數(shù)構(gòu)造出一個(gè)main_block_impl_0結(jié)構(gòu)體并賦給了一個(gè)指針恰画,這個(gè)即為block的c層面上的理解宾茂。
6.最后看main中的調(diào)用block部分:
OC: aBlock(); C: ((void (*)(__block_impl *))((__block_impl *)aBlock)->FuncPtr)((__block_impl *)aBlock);
這句代碼可簡化為*aBlock->impl.FuncPtr,即通過aBlock變量中的impl的FuncPtr函數(shù)指針調(diào)用函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拴还,一起剝皮案震驚了整個(gè)濱河市跨晴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌片林,老刑警劉巖端盆,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀骤,死亡現(xiàn)場離奇詭異,居然都是意外死亡爱谁,警方通過查閱死者的電腦和手機(jī)晒喷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來访敌,“玉大人凉敲,你說我怎么就攤上這事∷峦” “怎么了爷抓?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長阻塑。 經(jīng)常有香客問我蓝撇,道長,這世上最難降的妖魔是什么陈莽? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任渤昌,我火速辦了婚禮,結(jié)果婚禮上走搁,老公的妹妹穿的比我還像新娘独柑。我一直安慰自己,他們只是感情好私植,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布忌栅。 她就那樣靜靜地躺著,像睡著了一般曲稼。 火紅的嫁衣襯著肌膚如雪索绪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天贫悄,我揣著相機(jī)與錄音瑞驱,去河邊找鬼。 笑死清女,一個(gè)胖子當(dāng)著我的面吹牛钱烟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嫡丙,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼拴袭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了曙博?” 一聲冷哼從身側(cè)響起拥刻,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎父泳,沒想到半個(gè)月后般哼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吴汪,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年蒸眠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漾橙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡楞卡,死狀恐怖霜运,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蒋腮,我是刑警寧澤淘捡,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站池摧,受9級特大地震影響焦除,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜作彤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一膘魄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竭讳,春花似錦瓣距、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽成黄。三九已至呐芥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奋岁,已是汗流浹背思瘟。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闻伶,地道東北人滨攻。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像蓝翰,于是被迫代替她去往敵國和親光绕。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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

  • 前言 Blocks是C語言的擴(kuò)充功能畜份,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,757評論 0 23
  • Blocks Blocks Blocks 是帶有局部變量的匿名函數(shù) 截取自動(dòng)變量值 int main(){ ...
    南京小伙閱讀 911評論 1 3
  • 摘要block是2010年WWDC蘋果為Objective-C提供的一個(gè)新特性诞帐,它為我們開發(fā)提供了便利,比如GCD...
    西門吹雪123閱讀 903評論 0 4
  • Block基礎(chǔ)回顧 1.什么是Block爆雹? 帶有局部變量的匿名函數(shù)(名字不重要停蕉,知道怎么用就行)愕鼓,差不多就與C語言...
    Bugfix閱讀 6,748評論 5 61
  • 《Objective-C高級編程》這本書就講了三個(gè)東西:自動(dòng)引用計(jì)數(shù)、block慧起、GCD菇晃,偏向于從原理上對這些內(nèi)容...
    WeiHing閱讀 9,796評論 10 69