全面了解iOS中的Block

一榕吼、什么是Block?

Block是將函數(shù)及其執(zhí)行上下文封裝起來的對象。

比如:

NSIntegernum =3;

NSInteger(^block)(NSInteger) = ^NSInteger(NSIntegern){

????????return????n*num;? ?

?};? ? ? ??

block(2);

二、Block變量截獲

1奖年、局部變量截獲 是值截獲。

?比如:

NSIntegernum =3;

NSInteger(^block)(NSInteger) = ^NSInteger(NSIntegern){

? ??????return? ??n*num;? ??

};? ? ? ??

num =1;

NSLog(@"%zd",block(2));

這里的輸出是6而不是2沛贪,原因就是對局部變量num的截獲是值截獲陋守。

同樣震贵,在block里如果修改變量num,也是無效的水评,甚至編譯器會報錯猩系。

NSMutableArray* arr = [NSMutableArray????arrayWithObjects:@"1",@"2",nil];

void(^block)(void) = ^{

????????NSLog(@"%@",arr);//局部變量

????????[arr addObject:@"4"];? ??

};? ? ? ?

?[arr addObject:@"3"];? ? ? ?

?arr =nil;? ? ? ??

block();

打印為1,2中燥,3

局部對象變量也是一樣寇甸,截獲的是值,而不是指針疗涉,在外部將其置為nil拿霉,對block沒有影響,而該對象調(diào)用方法會影響

2咱扣、局部靜態(tài)變量截獲? 是指針截獲绽淘。

static????NSInteger????num =3;

NSInteger(^block)(NSInteger) = ^NSInteger(NSIntegern){

????????return????n*num;? ??

};? ? ? ?

?num =1;

NSLog(@"%zd",block(2));

輸出為2,意味著num = 1這里的修改num值是有效的闹伪,即是指針截獲沪铭。

同樣,在block里去修改變量m偏瓤,也是有效的杀怠。

三、Block的幾種形式

分為全局Block(_NSConcreteGlobalBlock)厅克、棧Block(_NSConcreteStackBlock)赔退、堆Block(_NSConcreteMallocBlock)三種形式

其中棧Block存儲在棧(stack)區(qū),堆Block存儲在堆(heap)區(qū)证舟,全局Block存儲在已初始化數(shù)據(jù)(.data)區(qū)

1离钝、不使用外部變量的block是全局block

比如:

NSLog(@"%@",[^{

????????NSLog(@"globalBlock");

}class]);

輸出:

__NSGlobalBlock__

2、使用外部變量并且未進行copy操作的block是棧block

比如:

NSInteger????num =10;

NSLog(@"%@",[^{

????????NSLog(@"stackBlock:%zd",num);? ??

}class]);

輸出:

__NSStackBlock__

日常開發(fā)常用于這種情況:

[self????testWithBlock:^{

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

}];

- (void)testWithBlock:(dispatch_block_t)block {? ??

????????block();

????????NSLog(@"%@",[block????class]);

}

3褪储、對棧block進行copy操作,就是堆block慧域,而對全局block進行copy鲤竹,仍是全局block

比如堆1中的全局進行copy操作即賦值:

void(^globalBlock)(void) = ^{

????????NSLog(@"globalBlock");? ??

};

NSLog(@"%@",[globalBlock????class]);

輸出:

__NSGlobalBlock__

仍是全局block

而對2中的棧block進行賦值操作:

NSInteger????num =10;

void(^mallocBlock)(void) = ^{

????????NSLog(@"stackBlock:%zd",num);? ??

};

NSLog(@"%@",[mallocBlock????class]);

輸出:

__NSMallocBlock__

對棧blockcopy之后,并不代表著棧block就消失了昔榴,左邊的mallock是堆block辛藻,右邊被copy的仍是棧block

比如:

[self????testWithBlock:^{

NSLog(@"%@",self);

}];

- (void)testWithBlock:(dispatch_block_t)block{? ??

????????block();? ? ? ??

????????dispatch_block_t tempBlock = block;

????????NSLog(@"%@,%@",[block????class],[tempBlock????class]);

}

輸出:

__NSStackBlock__ ?, ? __NSMallocBlock__

即如果對棧Block進行copy,將會copy到堆區(qū)互订,對堆Block進行copy吱肌,將會增加引用計數(shù),對全局Block進行copy仰禽,因為是已經(jīng)初始化的氮墨,所以什么也不做纺蛆。

另外,__block變量在copy時规揪,由于__forwarding的存在桥氏,棧上的__forwarding指針會指向堆上的__forwarding變量,而堆上的__forwarding指針指向其自身猛铅,所以字支,如果對__block的修改,實際上是在修改堆上的__block變量奸忽。

即__forwarding指針存在的意義就是堕伪,無論在任何內(nèi)存位置,? 都可以順利地訪問同一個__block變量栗菜。

另外由于block捕獲的__block修飾的變量會去持有變量欠雌,那么如果用__block修飾self,且self持有block苛萎,并且block內(nèi)部使用到__block修飾的self時桨昙,就會造成多循環(huán)引用,即self持有block腌歉,block 持有__block變量蛙酪,而__block變量持有self,造成內(nèi)存泄漏翘盖。

比如:

__block????typeof(self) weakSelf =self;? ? ? ??

_testBlock = ^{

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

};? ? ? ?

?_testBlock();

如果要解決這種循環(huán)引用桂塞,可以主動斷開__block變量對self的持有,即在block內(nèi)部使用完weakself后馍驯,將其置為nil阁危,但這種方式有個問題,如果block一直不被調(diào)用汰瘫,那么循環(huán)引用將一直存在狂打。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市混弥,隨后出現(xiàn)的幾起案子趴乡,更是在濱河造成了極大的恐慌,老刑警劉巖蝗拿,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晾捏,死亡現(xiàn)場離奇詭異,居然都是意外死亡哀托,警方通過查閱死者的電腦和手機惦辛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仓手,“玉大人胖齐,你說我怎么就攤上這事玻淑。” “怎么了市怎?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵岁忘,是天一觀的道長。 經(jīng)常有香客問我区匠,道長干像,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任驰弄,我火速辦了婚禮麻汰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘戚篙。我一直安慰自己五鲫,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布岔擂。 她就那樣靜靜地躺著位喂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪乱灵。 梳的紋絲不亂的頭發(fā)上塑崖,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音痛倚,去河邊找鬼规婆。 笑死,一個胖子當(dāng)著我的面吹牛蝉稳,可吹牛的內(nèi)容都是我干的抒蚜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼耘戚,長吁一口氣:“原來是場噩夢啊……” “哼嗡髓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起收津,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤器贩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后朋截,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡吧黄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年部服,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拗慨。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡廓八,死狀恐怖奉芦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情剧蹂,我是刑警寧澤声功,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站宠叼,受9級特大地震影響先巴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冒冬,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一伸蚯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧简烤,春花似錦剂邮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至枉侧,卻和暖如春引瀑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棵逊。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工伤疙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辆影。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓徒像,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛙讥。 傳聞我的和親對象是個殘疾皇子锯蛀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

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

  • Block的底層基本結(jié)構(gòu) 通過clang命令查看編譯器是如何實現(xiàn)Block的,在終端輸入clang -rewrit...
    小涼介閱讀 20,169評論 22 96
  • Block概要 Block:帶有自動變量的匿名函數(shù)次慢。 匿名函數(shù):沒有函數(shù)名的函數(shù)旁涤,一對{}包裹的內(nèi)容是匿名函數(shù)的作...
    zweic閱讀 502評論 0 2
  • 在介紹Block之前通過一個簡單的應(yīng)用場景認(rèn)識下Block 場景描述如下:TableView上面有多個Custom...
    黑_白_灰閱讀 1,388評論 4 29
  • Block作為Objective-C中閉包的實現(xiàn)在iOS開發(fā)中占有非常重要的地位,尤其是作為回調(diào)(callback...
    NotFunGuy閱讀 746評論 0 4
  • 每個同學(xué)都是“寒窗苦讀了十二載”才考上了大學(xué)迫像∨蓿或許自己所上的大學(xué)并不是自己心心念念的那一所,但不管怎么說闻妓,這是自己...
    王詩嫻閱讀 655評論 1 0