OC中Block的使用分析

一,首先介紹什么是Block榜旦?它就是一個(gè)(里面存儲(chǔ)了 指向函數(shù)體中包含定義block時(shí)的代碼塊的函數(shù)指針,以及block外部上下文變量等信息的)結(jié)構(gòu)體咐旧。

二铣墨,在OC中伊约,有三種類型的Block:

1屡律,_NSConcreteGlobalBlock ?保存在全局區(qū)

2,_NSConcreteStackBlock ?保存在棧中

3降淮,_NSConcreteMallocBlock? 保存在堆中

在代碼中超埋,具體怎么判斷屬于哪種類型呢?請(qǐng)看下面demo

提示:該demo是在MRC的環(huán)境下運(yùn)行的佳鳖。

@implementation ViewController

- (void)viewDidLoad {

? ?[super viewDidLoad];

// 一

NSInteger i = 10;

void(^oneBlock)(void) = ^{

NSLog(@"%zd", i);

};

NSLog(@"%@", oneBlock);?

//打印結(jié)果:__NSStackBlock__

//二

void(^twoBlock)(void) = ^{

};

NSLog(@"%@",twoBlock);

//打印結(jié)果:__NSGlobalBlock__

//三

void(^threeBlock)(void) = [oneBlock copy];

NSLog(@"%@",threeBlock);

//打印結(jié)果:__NSMallocBlock__

}

@end

log信息:

2017-08-17 09:47:08.514 test[1008:27892] <__NSStackBlock__: 0xbff12f38>

2017-08-17 09:47:08.515 test[1008:27892] <__NSGlobalBlock__: 0xee060>

2017-08-17 09:47:08.515 test[1008:27892] <__NSMallocBlock__: 0x79789a30>

結(jié)果分析:

1霍殴,oneBlock使用了外部變量,地址顯示在棧區(qū)(MRC)系吩。

2来庭,twoBlock沒(méi)有使用外部變量,地址顯示在全局區(qū)(ARC和MRC一樣)穿挨。

由1和2得出結(jié)論月弛,如果block沒(méi)有訪問(wèn)外部變量,那么該block是NSGlobalBlock尊搬,如果訪問(wèn)了外部變量冀泻,那么該block是NSStackBlock肢专。

3,在對(duì)棧區(qū)oneBlock進(jìn)行copy之后,得到的threeBlock地址顯示在堆區(qū)苗傅。

由3得出結(jié)論:對(duì)棧區(qū)block進(jìn)行copy之后的得到的新block在堆區(qū)旱物。

通過(guò)這張表我們可以清晰看到三種Block copy之后到底做了什么

其實(shí)在使用__block變量的Block從棧上復(fù)制到堆上時(shí),__block變量也被從棧復(fù)制到堆上并被Block所持有。

三府蔗,變量的復(fù)制

對(duì)于 block 外的變量引用不铆,block 默認(rèn)是將其復(fù)制到其數(shù)據(jù)結(jié)構(gòu)中來(lái)實(shí)現(xiàn)訪問(wèn)的,如果對(duì)象是引用類型,則block會(huì)將其引用計(jì)數(shù)加一 ,如下圖所示:

對(duì)于用 __block 修飾的外部變量引用,block 是復(fù)制其引用地址來(lái)實(shí)現(xiàn)訪問(wèn)的茄袖,如下圖所示:

四,ARC對(duì)block的影響

在ARC模式下涯呻,在棧間傳遞block時(shí)胀滚,不需要手動(dòng)copy棧中的block剑刑,即可讓block正常工作媳纬。主要原因是ARC對(duì)棧中的block自動(dòng)執(zhí)行了copy钮惠,將_NSConcreteStackBlock類型的block轉(zhuǎn)換成了_NSConcreteMallocBlock的block预明。

@interface ViewController : UIViewController

@property (strong,nonatomic)void (^block)();

@property (weak,nonatomic)void (^weakBlock)();

@property (strong,nonatomic)void (^stackBlock)();

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//

NSInteger i = 10;

self.block = ^{

NSLog(@"%zd", i);

};

NSLog(@"%@", self.block);

//

self.weakBlock = ^{

NSLog(@"%zd", i);

};

NSLog(@"%@", self.weakBlock);

//

self.stackBlock = ^{};

NSLog(@"%@", self.stackBlock);

}

打印結(jié)果:

2017-08-17 13:24:32.088 test[1882:89514] <__NSMallocBlock__: 0x7ba2a200>

2017-08-17 13:24:32.088 test[1882:89514] <__NSStackBlock__: 0xbff3ef20>

2017-08-17 13:24:32.089 test[1882:89514] <__NSGlobalBlock__: 0xc2080>

結(jié)論:

1卤材,ARC會(huì)自動(dòng)幫strong類型且捕獲外部變量的block進(jìn)行copy。

2,ARC不會(huì)幫weak類型且捕獲外部變量的block進(jìn)行copy冰评。

此時(shí)weakBlock是在棧內(nèi)存上映胁,由于棧內(nèi)存有生命周期的約束,所以在運(yùn)行到touchesBegan方法的時(shí)候甲雅,weakBlock已經(jīng)被釋放了解孙,程序會(huì)奔潰。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

self.weakBlock();

}

重點(diǎn):研究block屬性用strong抛人,weak妆距,還是copy修飾的目的,就是保證block在使用的時(shí)候不會(huì)出現(xiàn)被釋放的情況函匕。

這里還有一點(diǎn)關(guān)于block類型的ARC屬性。上文也說(shuō)明了蚪黑,ARC會(huì)自動(dòng)幫strong類型且捕獲外部變量的block進(jìn)行copy盅惜,所以在定義block類型的屬性時(shí)也可以使用strong,不一定使用copy忌穿。也就是以下代碼:

/** 假如有棧block賦給以下兩個(gè)屬性 **/

// 這里因?yàn)锳RC抒寂,當(dāng)棧block中會(huì)捕獲外部變量時(shí),這個(gè)block會(huì)被copy進(jìn)堆中

// 如果沒(méi)有捕獲外部變量掠剑,這個(gè)block會(huì)變?yōu)槿诸愋?/p>

// 不管怎么樣屈芜,它都脫離了棧生命周期的約束

// 這里都會(huì)被copy進(jìn)堆中

@property (strong, nonatomic) Block *strongBlock;

@property (copy, nonatomic) Block *copyBlock;


五:在開(kāi)發(fā)中的應(yīng)用場(chǎng)景

1,block作為類的屬性朴译,在需要的時(shí)候去調(diào)用井佑。

2,block作為方法的參數(shù)使用眠寿,在函數(shù)的內(nèi)部去調(diào)用躬翁,由外界去定義。

3盯拱,block作為方法的返回值使用盒发,在函數(shù)的內(nèi)部去定義,由外界去調(diào)用狡逢,目的是替代方法宁舰。

項(xiàng)目中注意事項(xiàng):1,循環(huán)引用的問(wèn)題奢浑。2蛮艰,聲明block屬性的修飾符問(wèn)題。3殷费,block訪問(wèn)外部變量的問(wèn)題印荔。


參考文章:www.cocoachina.com/ios/20161025/17198.html

blog.devtang.com/2013/07/28/a-look-inside-blocks/

Block技巧與底層解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末低葫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子仍律,更是在濱河造成了極大的恐慌嘿悬,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件水泉,死亡現(xiàn)場(chǎng)離奇詭異善涨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)草则,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)钢拧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人炕横,你說(shuō)我怎么就攤上這事源内。” “怎么了份殿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵膜钓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我卿嘲,道長(zhǎng)颂斜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任拾枣,我火速辦了婚禮沃疮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梅肤。我一直安慰自己司蔬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布姨蝴。 她就那樣靜靜地躺著葱她,像睡著了一般。 火紅的嫁衣襯著肌膚如雪似扔。 梳的紋絲不亂的頭發(fā)上吨些,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音炒辉,去河邊找鬼豪墅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛黔寇,可吹牛的內(nèi)容都是我干的偶器。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼屏轰!你這毒婦竟也來(lái)了颊郎?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤霎苗,失蹤者是張志新(化名)和其女友劉穎姆吭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體唁盏,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡内狸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厘擂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昆淡。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖刽严,靈堂內(nèi)的尸體忽然破棺而出昂灵,到底是詐尸還是另有隱情,我是刑警寧澤舞萄,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布倔既,位于F島的核電站,受9級(jí)特大地震影響鹏氧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜佩谣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一把还、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茸俭,春花似錦吊履、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腾窝,卻和暖如春缀踪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背虹脯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工驴娃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人循集。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓唇敞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疆柔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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