block

block的原理是怎樣的领炫?本質(zhì)是什么膛腐?

block本質(zhì)上是一個(gè)OC對(duì)象 他內(nèi)部也有isa指針
block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境的OC對(duì)象

__block的作用是什么?有什么使用注意點(diǎn)执解?

解決block內(nèi)部無(wú)法修改auto變量值的問(wèn)題
會(huì)把__block變量包裝成一個(gè)對(duì)象

block的屬性修飾詞為什么是copy寞肖?使用block有哪些使用注意?

block一旦沒(méi)有進(jìn)行copy操作 就不會(huì)在堆上
注意循環(huán)引用的問(wèn)題

block在修改NSMutableArray衰腌,需不需要添加__block新蟆?

不需要
__block是修改auto變量的值
NSMutableArray addobject是使用了這個(gè)指針

block本質(zhì)

block本質(zhì)上是一個(gè)OC對(duì)象 他內(nèi)部也有isa指針
block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境的OC對(duì)象
block本質(zhì).png

block的變量捕獲(capture)

auto 自動(dòng)變量 離開(kāi)作用域就銷(xiāo)毀
只要是局部變量 block要訪問(wèn)局部變量 就要捕獲

#block的變量捕獲.png

自動(dòng)變量只能傳值的原因是隨時(shí)可能會(huì)銷(xiāo)毀 那塊地址就沒(méi)了 如果再傳地址進(jìn)去 就會(huì)訪問(wèn)到壞內(nèi)存 static變量是因?yàn)槟菈K內(nèi)存存在 可以通過(guò)地址來(lái)進(jìn)行訪問(wèn)
局部變量需要捕獲的原因是因?yàn)橐绾瘮?shù)訪問(wèn) 全局變量是任何函數(shù)都可以直接使用,所以不需要進(jìn)行捕獲

block的類(lèi)型

block有3種類(lèi)型,可以通過(guò)調(diào)用class方法或者isa指針查看具體類(lèi)型右蕊,最終都是繼承自NSBlock類(lèi)型

__NSGlobalBlock__ ( _NSConcreteGlobalBlock )
__NSStackBlock__  ( _NSConcreteStackBlock )
__NSMallocBlock__ ( _NSConcreteMallocBlock )

一切以運(yùn)行時(shí)的結(jié)果為準(zhǔn) 使用Clang轉(zhuǎn)成的C++代碼不一定完全一致 只能作為參考

block的三種類(lèi)型分別存放的位置.png

根據(jù)環(huán)境判斷block類(lèi)型.png

在棧block里面 函數(shù)調(diào)用完畢 里面的數(shù)據(jù)可能是垃圾數(shù)據(jù)

block類(lèi)調(diào)用copy后的結(jié)果.png

在ARC環(huán)境下憎妙,編譯器會(huì)根據(jù)情況自動(dòng)將棧上的block復(fù)制到堆上

1.block作為函數(shù)返回值的時(shí)候
2.將block賦值給強(qiáng)指針(__strong)的時(shí)候
3.block作為Cocoa API中方法名含有usingBlock的方法參數(shù)時(shí)
4.block作為GCD API的方法參數(shù)時(shí)

椩俨祝空間的block是無(wú)法對(duì)外面的變量進(jìn)行持有的 也就是強(qiáng)引用的 堆空間的block會(huì)對(duì)外面的變量進(jìn)行強(qiáng)引用的 保住他的生命(當(dāng)block銷(xiāo)毀的時(shí)候 也會(huì)對(duì)變量進(jìn)行release)

如果代碼里面使用了__weak 在使用clang轉(zhuǎn)換OC為C++代碼時(shí)宾濒,可能會(huì)遇到cannot create __weak reference in file using manual reference 那么需要指定運(yùn)行時(shí)版本 需要arc

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

對(duì)象類(lèi)型的auto變量

當(dāng)block內(nèi)部訪問(wèn)了對(duì)象類(lèi)型的auto變量時(shí)
  1.如果block是在棧上 都不會(huì)對(duì)auto變量產(chǎn)生強(qiáng)引用
  2.如果block被拷貝到堆上
    @.會(huì)調(diào)用block內(nèi)部的copy函數(shù)
    @.copy函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_assign函數(shù)
    @._Block_object_assign 函數(shù)會(huì)根據(jù)auto變量的修飾符(__strong宠进、__weak、__unsafe_unretained)做出
     相應(yīng)的操作萝风,形成強(qiáng)引用(retain)或者弱引用
  3.如果block從堆上移除
    @.會(huì)調(diào)用block內(nèi)部的dispose函數(shù)
    @.dispose函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_dispose函數(shù)
    @._Block_object_dispose函數(shù)會(huì)自動(dòng)釋放引用的auto變量 類(lèi)似于release
調(diào)用時(shí)機(jī).png

解決block內(nèi)部無(wú)法修改auto變量值的問(wèn)題

1.使用static修飾 會(huì)把變量地址捕獲到block里面
2.使用全局變量來(lái) 不會(huì)捕獲到block里面 直接就可以修改
3.使用__block修飾

不使用static變量和全局變量的原因是 不想創(chuàng)建一個(gè)變量永遠(yuǎn)占據(jù)這塊內(nèi)存
__block不能修飾全局變量嘀掸、靜態(tài)變量(static)
編譯器會(huì)將__block變量包裝成一個(gè)對(duì)象

block的內(nèi)部結(jié)構(gòu).png

__block修飾的變量會(huì)變成一個(gè)對(duì)象 就是一個(gè)結(jié)構(gòu)體.png

__block變量的結(jié)構(gòu)體的內(nèi)部結(jié)構(gòu).png

__block修飾auto變量的內(nèi)存管理

__block修飾變量的時(shí)候
1.當(dāng)block在棧上時(shí) 并不會(huì)對(duì)__block變量產(chǎn)生強(qiáng)引用
2.當(dāng)block被copy到堆時(shí)
  a.會(huì)調(diào)用block內(nèi)部的copy函數(shù)
  b.copy函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_assign函數(shù)
  c. _Block_object_assign函數(shù)會(huì)對(duì)__block變量形成強(qiáng)引用(retain)
圖1.png

圖2.png
block銷(xiāo)毀的時(shí)候
當(dāng)block從堆中移除時(shí)
- 會(huì)調(diào)用block內(nèi)部的dispose函數(shù)
- dispose函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_dispose函數(shù)
- _Block_object_dispose函數(shù)會(huì)自動(dòng)釋放引用的__block變量(release)
image1.png

image2.png

對(duì)象類(lèi)型的auto變量、__block修飾的auto變量的內(nèi)存管理總結(jié)

1.當(dāng)block在棧上的時(shí)候 都不會(huì)產(chǎn)生強(qiáng)引用
2.當(dāng)block拷貝到堆上時(shí)  通過(guò)copy函數(shù)處理他們
  a. __block變量(假設(shè)變量名叫做a)
   _Block_object_assign((void*)&dst->a, (void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);  
  b.對(duì)象類(lèi)型的auto變量(假設(shè)變量名叫做p)
  _Block_object_assign((void*)&dst->p, (void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);
3.當(dāng)block從堆上移除時(shí)规惰,都會(huì)通過(guò)dispose函數(shù)來(lái)釋放它們
  a.__block變量(假設(shè)變量名叫做a)
   _Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);
  b.對(duì)象類(lèi)型的auto變量(假設(shè)變量名叫做p)
   _Block_object_dispose((void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);

__block的__forwarding指針

__forwarding指針.png

保證不管訪問(wèn)的是棧中的block還是堆中的block 只要通過(guò)__forwarding指針都可以訪問(wèn)到堆中的block

__block修飾對(duì)象類(lèi)型的內(nèi)存管理

當(dāng)block拷貝到堆上 會(huì)把__block修飾的對(duì)象這個(gè)整體的結(jié)構(gòu)體拷貝到堆上 同時(shí),會(huì)調(diào)用這個(gè)結(jié)構(gòu)體內(nèi)部的copy函數(shù)

1.當(dāng)__block變量在棧上時(shí)睬塌,不會(huì)對(duì)指向的對(duì)象產(chǎn)生強(qiáng)引用
2.當(dāng)__block變量被copy到堆時(shí)
  a.會(huì)調(diào)用__block變量?jī)?nèi)部的copy函數(shù)
  b.copy函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_assign函數(shù)
  c._Block_object_assign函數(shù)會(huì)根據(jù)所指向?qū)ο蟮男揎椃╛_strong、__weak歇万、__unsafe_unretained)做出相應(yīng)
  的操作揩晴,形成強(qiáng)引用(retain)或者弱引用(注意:這里僅限于ARC時(shí)會(huì)retain,MRC時(shí)不會(huì)retain)
3.如果__block變量從堆上移除
  a.會(huì)調(diào)用__block變量?jī)?nèi)部的dispose函數(shù)
  b.dispose函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_dispose函數(shù)
  c._Block_object_dispose函數(shù)會(huì)自動(dòng)釋放指向的對(duì)象(release)

這里僅限于ARC時(shí)會(huì)retain堕花,MRC時(shí)不會(huì)retain

解決循環(huán)引用問(wèn)題 -ARC

用__weak文狱、__unsafe_unretained解決

weak 不會(huì)產(chǎn)生強(qiáng)引用 指向的對(duì)象銷(xiāo)毀時(shí) 會(huì)自動(dòng)讓指針置為nil
__unsafe_unretained 不會(huì)產(chǎn)生強(qiáng)引用 不安全 指向的對(duì)象銷(xiāo)毀時(shí) 指針存儲(chǔ)的地址值不變

可以使用__block來(lái)解決循環(huán)引用問(wèn)題 但是 必須要執(zhí)行block 和把對(duì)象置為nil 如果沒(méi)有執(zhí)行block 那么就會(huì)存在循環(huán)引用

__block id weakSelf = self;
self.block = ^{
  printf( "%p", weakSelf);
  weakSelf = nil ;
};
self.block() ;

解決循環(huán)引用問(wèn)題 -MRC

在MRC下不支持__weak

用__block、__unsafe_unretained解決

由于在MRC下 使用__block修飾變量 不會(huì)對(duì)變量產(chǎn)生強(qiáng)引用 這樣就可以使用__block來(lái)解決循環(huán)引用問(wèn)題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缘挽,一起剝皮案震驚了整個(gè)濱河市瞄崇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌壕曼,老刑警劉巖苏研,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異腮郊,居然都是意外死亡摹蘑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)轧飞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)衅鹿,“玉大人撒踪,你說(shuō)我怎么就攤上這事〈蟛常” “怎么了制妄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)泵三。 經(jīng)常有香客問(wèn)我耕捞,道長(zhǎng),這世上最難降的妖魔是什么烫幕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任俺抽,我火速辦了婚禮,結(jié)果婚禮上较曼,老公的妹妹穿的比我還像新娘磷斧。我一直安慰自己,他們只是感情好诗芜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布瞳抓。 她就那樣靜靜地躺著埃疫,像睡著了一般伏恐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上栓霜,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天翠桦,我揣著相機(jī)與錄音,去河邊找鬼胳蛮。 笑死销凑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仅炊。 我是一名探鬼主播斗幼,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抚垄!你這毒婦竟也來(lái)了蜕窿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤呆馁,失蹤者是張志新(化名)和其女友劉穎桐经,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體浙滤,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阴挣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纺腊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畔咧。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茎芭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出誓沸,到底是詐尸還是另有隱情骗爆,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布蔽介,位于F島的核電站摘投,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏虹蓄。R本人自食惡果不足惜犀呼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望薇组。 院中可真熱鬧外臂,春花似錦、人聲如沸律胀。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)炭菌。三九已至罪佳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間黑低,已是汗流浹背赘艳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留克握,地道東北人蕾管。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像菩暗,于是被迫代替她去往敵國(guó)和親掰曾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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