block的底層原理

block的底層結(jié)構(gòu):

  • block定義:block的本質(zhì)是一個的OC對象瑰步,內(nèi)部有一個isa指針贵白,它封裝了函數(shù)和調(diào)用函數(shù)所需要的參數(shù)衣吠,block中有一個變量捕獲機制锰什,正是因為這個變量捕獲機制罚随,block才能封裝函數(shù)的調(diào)用環(huán)境玉工。
  • block的底層結(jié)構(gòu)圖:


    block的底層結(jié)構(gòu).png

block的變量捕獲(capture)

  • 為了保證在block內(nèi)部能夠訪問外部變量,block有個變量的捕獲機制淘菩。block對局部變量和全局變量的訪問方式是不同的
  • auto:當前變量的作用域為當前函數(shù)或代碼塊內(nèi)遵班,當前變量時一個局部變量屠升,當前變量會在棧區(qū)上進行分配存儲空間。
    block的變量捕獲機制介紹.png
  • 在block中直接使用到成員變量也會捕獲self狭郑。

block的類型

  • 可以通過調(diào)用class方法或者isa指針查看block的具體類型腹暖,最終都是繼承NSBlock類型

  • block的三種類型:

block的類型 環(huán)境
__NSGlobalBlock__ 沒有訪問auto變量
__NSStackBlock__ 訪問了auto變量
__NSMallocBlock__ __NSStackBlock__ 調(diào)用了copy之后
  • block每種類型在內(nèi)存中存儲的區(qū)域:
    block的存儲區(qū)域.png
  • 在ARC環(huán)境下,編譯器會根據(jù)情況自動將棧上的block復制到堆上

    • block作為函數(shù)的返回值時
    • block賦值給__strong指針時
    • block作為Cocoa API中方法名含有usingBlock的方法參數(shù)時
    • block作為GCD API的方法參數(shù)時
  • MRC下block屬性修飾關(guān)鍵字一定要使用copy:

    • @property (copy, nonatomic) void (^block)(void);
  • ARC下Block屬性修飾關(guān)鍵字建議使用copy(使用strong和使用copy的效果是一樣的):

    • @property (strong, nonatomic) void (^block)(void);
    • @property (copy, nonatomic) void (^block)(void);
  • 每種類型的block調(diào)用了多次copy之后:
    block被copy之后存儲位置的變化.png
  • block內(nèi)部訪問了對象類型的auto變量時:

    • 如果block是在棧上的時候翰萨,不會對auto變量產(chǎn)生強引用

    • 如果block被copy到堆上的時候

      • 會調(diào)用block內(nèi)部的copy函數(shù)脏答,copy函數(shù)會調(diào)用_Block_object_assign函數(shù)
      • _Block_object_assign函數(shù)會根據(jù)auto變量的修飾符決定得是強引用或者弱引用。
    • 如果block從堆上移除的時候

      • 會調(diào)用block內(nèi)部的dispose函數(shù),dispose函數(shù)會調(diào)用_Block_object_dispose函數(shù)
      • _Block_object_dispose函數(shù)會自動對強引用的auto變量做一次release

__block的原理

  • __block的本質(zhì)

    • __block可以用來解決在block內(nèi)部無法修改auto變量的問題亩鬼,編譯器會將__block修飾的變量封裝成一個對象殖告。
    • __block只能用來修飾auto變量,不能修飾static 和全局變量
      __block的本質(zhì).png
  • 捕獲了OC對象或者捕獲了使用__block修飾的臨時變量的block結(jié)構(gòu)體中為什么會有forwaring指針?
    __block的forwarding指針.png
  • block對__block變量的內(nèi)存管理

    • block對__block變量的內(nèi)存管理
    • 當block棧上的時候并不會對__block變量產(chǎn)生強引用雳锋。 當block被copy到堆上的時候會調(diào)用block內(nèi)部的copy函數(shù)黄绩,copy函數(shù)會調(diào)用_Block_object_assign函數(shù),_Block_object_assign函數(shù)會對__block變量強引用魄缚。
    • 當block從堆中移除的時候宝与,會調(diào)用block的dispose函數(shù),dispose函數(shù)會調(diào)用_Block_object_dispose函數(shù),__Block_object_dispose函數(shù)會對__block變量做一次release
  • __block變量對修飾的對象類型的內(nèi)存管理

    • __block變量在棧上的時候不會對__block內(nèi)部的變量產(chǎn)生強引用
    • 當__block變量被copy到堆上的時候 會調(diào)用__block變量內(nèi)部的copy方法冶匹。 copy方法會調(diào)用 __Block_object_assign 函數(shù)习劫,_Block_object_assign函數(shù)會根據(jù)所指向?qū)ο蟮男揎椃麤Q定是強指針還是弱指針(僅僅是ARC環(huán)境下,在MRC環(huán)境下一定不會retain)
    • 當__block變量從堆上移除的時候會調(diào)用__block變量內(nèi)部的dospose函數(shù)嚼隘, dispose函數(shù)會調(diào)用_Block_object_dispose诽里,_Block_object_dispose會對指向的對象做一次release


      ARC編譯環(huán)境下block的內(nèi)存管理流程圖整理.jpg

      block從棧上拷貝到堆上.png

block的循環(huán)引用

  • block產(chǎn)生循環(huán)引用的原因

  • 在block中使用了self或者成員變量
    在block中使用成員變量的循環(huán)引用.png
  • __block變量產(chǎn)生的循環(huán)引用

  • __block變量持有對象

  • 對象持有block

  • block持有__block
    __block變量的循環(huán)引用.png
  • 解決block的循環(huán)引用的方法

  • 在ARC下的方法:

    1. __weak、__unsafe_unretained 關(guān)鍵字來解決循環(huán)引用
    2. 使用__block變量來解決循環(huán)引用(必須要調(diào)用block)
  • 在MRC下的方法

    • 使用__unsafe_unretained 或者__block來解決循環(huán)引用

其他

  • 使用clang 將OC代碼轉(zhuǎn)換為C++代碼

  • xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m -o main_cpp.cpp

  • block源碼地址
    點擊這里下載

  • 本文檔對應對應的github地址 歡迎start

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末飞蛹,一起剝皮案震驚了整個濱河市谤狡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卧檐,老刑警劉巖墓懂,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異霉囚,居然都是意外死亡捕仔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門盈罐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榜跌,“玉大人,你說我怎么就攤上這事盅粪〉龊” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵票顾,是天一觀的道長础浮。 經(jīng)常有香客問我帆调,道長,這世上最難降的妖魔是什么豆同? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任贷帮,我火速辦了婚禮,結(jié)果婚禮上诱告,老公的妹妹穿的比我還像新娘。我一直安慰自己民晒,他們只是感情好精居,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潜必,像睡著了一般靴姿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磁滚,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天佛吓,我揣著相機與錄音,去河邊找鬼垂攘。 笑死维雇,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的晒他。 我是一名探鬼主播吱型,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼陨仅!你這毒婦竟也來了津滞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤灼伤,失蹤者是張志新(化名)和其女友劉穎触徐,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狐赡,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡撞鹉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了猾警。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片孔祸。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖发皿,靈堂內(nèi)的尸體忽然破棺而出崔慧,到底是詐尸還是另有隱情,我是刑警寧澤穴墅,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布惶室,位于F島的核電站温自,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏皇钞。R本人自食惡果不足惜悼泌,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望夹界。 院中可真熱鬧馆里,春花似錦、人聲如沸可柿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽复斥。三九已至营密,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間目锭,已是汗流浹背评汰。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留痢虹,地道東北人被去。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像世分,于是被迫代替她去往敵國和親编振。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

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