偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

iOS中Block介紹(二)內(nèi)存管理與其他特性

移動(dòng)開(kāi)發(fā) iOS
我們?cè)谇耙徽陆榻B了block的用法,而正確使用block必須要求正確理解block的內(nèi)存管理問(wèn)題。這一章,我們只陳述結(jié)果而不追尋原因,我們將在下一章深入其原因。

一、block放在哪里

我們針對(duì)不同情況來(lái)討論block的存放位置:

1.棧和堆

以下情況中的block位于堆中:

  1. void foo()  
  2. {  
  3.     __block int i = 1024;  
  4.     int j = 1;  
  5.     void (^blk)(void);  
  6.     void (^blkInHeap)(void);  
  7.     blk = ^{ printf("%d, %d\n", i, j);};//blk在棧里  
  8.     blkInHeap = Block_copy(blk);//blkInHeap在堆里  
  9. }  
  10.    
  11. - (void)fooBar  
  12. {  
  13.     _oi = 1;  
  14.     OBJ1* oj = self;  
  15.     void (^oblk)(void) = ^{ printf("%d\n", oj.oi);};  
  16.     void (^oblkInHeap)(void) = [oblk copy];//oblkInHeap在堆中  

2.全局區(qū)

以下情況中的block位于全局區(qū):

  1. static int(^maxIntBlock)(intint) = ^(int a, int b){return a>b?a:b;};  
  2. - (void)fooBar  
  3. {  
  4.      int(^maxIntBlockCopied)(intint) =[maxIntBlock copy];  
  5. }  
  6. void foo()  
  7. {  
  8.      int(^maxIntBlockCopied)(intint) = Block_copy(maxIntBlock);  

需要注意的是,這里復(fù)制過(guò)后的block依舊位于全局區(qū),實(shí)際上,復(fù)制操作是直接返回了原block對(duì)象。

二、block引用的變量在哪里

 1.全局區(qū)

全局區(qū)的變量存儲(chǔ)位置與block無(wú)關(guān):

  1. static int gVar = 0;  
  2. //__block static int gMVar = 1;  
  3. void foo()  
  4. {  
  5.     static int stackVar = 0;  
  6. //    __block static int stackMVar = 0;  

注意:static變量是不允許添加__block標(biāo)記的

2.堆棧

此時(shí),你可能會(huì)問(wèn),當(dāng)函數(shù)foo返回后,棧上的j已經(jīng)回收,那么blkInHeap怎么能繼續(xù)使用它?這是因?yàn)闆](méi)有__block標(biāo)記的變量,會(huì)被當(dāng)做實(shí)參傳入block的底層實(shí)現(xiàn)函數(shù)中,當(dāng)block中的代碼被執(zhí)行時(shí),j已經(jīng)不是原來(lái)的j了,所謂物是人非就是這樣吧~

另外,如果使用到變量j的所有block都沒(méi)有被復(fù)制至heap,那么這個(gè)變量j也不會(huì)被復(fù)制至heap。

因此,即使將j++這一句放到blk()這句之前,這段代碼執(zhí)行后,控制臺(tái)打印結(jié)果也是:1024, 1。而不是1024, 2

三、其他特性

1.復(fù)制的行為

對(duì)block調(diào)用復(fù)制,有以下幾種情況:

1.對(duì)全局區(qū)的block調(diào)用copy,會(huì)返回原指針,并且這期間不處理任何東西(至少目前的內(nèi)部實(shí)現(xiàn)是這樣);

2.對(duì)棧上的block調(diào)用copy,每次會(huì)返回新復(fù)制到堆上的block的指針,同時(shí),所有__block變量都會(huì)被復(fù)制至堆一份(多次拷貝,只會(huì)生成一份)。

3.對(duì)已經(jīng)位于heap上的block,再次調(diào)用copy,只會(huì)增加block的引用計(jì)數(shù)。

為什么我們不討論retian的行為?原因是并沒(méi)有Block_retain()這樣的函數(shù),而且objc里面的retain消息發(fā)送給block對(duì)象后,其內(nèi)部實(shí)現(xiàn)是什么都不做。

2.objc類(lèi)中的block復(fù)制

objc類(lèi)實(shí)例方法中的block如果被復(fù)制至heap,那么當(dāng)前實(shí)例會(huì)被增加引用計(jì)數(shù),當(dāng)這個(gè)block被釋放時(shí),此實(shí)例會(huì)被減少引用計(jì)數(shù)。

但如果這個(gè)block沒(méi)有使用當(dāng)前實(shí)例的任何成員,那么當(dāng)前實(shí)例不會(huì)被增加引用計(jì)數(shù)。這也是很自然的道理,我既然沒(méi)有用到這個(gè)instance的任何東西,那么我干嘛要retian它?

我們要注意的一點(diǎn)是,我看到網(wǎng)上有很多人說(shuō)block引起了實(shí)例與block之間的循環(huán)引用(retain-cycle),并且給出解決方案:不直接使用self而先將self賦值給一個(gè)臨時(shí)變量,然后再使用這個(gè)臨時(shí)變量。

但是,大家注意,我們一定要為這個(gè)臨時(shí)變量增加__block標(biāo)記(多謝第三篇文章回帖網(wǎng)友的提醒)。

這一章我們以結(jié)果導(dǎo)向的方式來(lái)說(shuō)明了各種情況下,block的內(nèi)存問(wèn)題,下一章,我將剖析運(yùn)行時(shí)庫(kù)的源碼,從根源闡述block的行為。也就是過(guò)程導(dǎo)向的方式了。

責(zé)任編輯:閆佳明 來(lái)源: dreamingwish
相關(guān)推薦

2013-07-19 12:52:50

iOS中BlockiOS開(kāi)發(fā)學(xué)習(xí)

2013-07-22 14:38:00

iOS開(kāi)發(fā)ASIHTTPRequ

2013-07-19 14:00:13

iOS中BlockiOS開(kāi)發(fā)學(xué)習(xí)

2013-07-19 14:35:59

iOS中BlockiOS開(kāi)發(fā)學(xué)習(xí)

2021-04-28 11:20:39

Python內(nèi)存代碼

2020-12-29 08:09:25

JavaScript內(nèi)存管理

2014-07-30 11:12:09

block

2018-07-23 09:26:08

iOS內(nèi)存優(yōu)化

2023-12-18 16:14:01

生成式AIIT

2012-02-23 10:28:12

MySQL

2017-03-07 10:15:35

iOS內(nèi)存管理開(kāi)發(fā)

2017-03-07 09:45:43

iOSBlock開(kāi)發(fā)

2011-08-08 18:11:45

IOS 4Block UIActionShe

2011-08-05 16:41:48

iOS 隊(duì)列 內(nèi)存

2010-01-15 14:46:20

C++語(yǔ)言

2010-02-07 10:46:50

Android系統(tǒng)

2011-07-21 14:42:45

iOS UIViewCont 內(nèi)存

2015-03-13 09:30:23

iOS內(nèi)存管理

2009-06-16 11:11:07

Java內(nèi)存管理Java內(nèi)存泄漏

2011-08-22 11:07:16

IOS 開(kāi)發(fā)多核內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)