關於block和引用計數

2021-07-10 08:13:23 字數 1529 閱讀 8808

(1)修飾block

如果需要block在它被宣告的作用域被銷毀後繼續使用的話,你就需要做乙份拷貝。拷貝會把block移到堆裡面。所以,使用@property時設定通常如下:

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

(2)retain cycle的問題

block在實現時就會對它引用到的它所在方法中定義的棧變數進行一次唯讀拷貝,然後在block塊內使用該唯讀拷貝。所以在使用block過程中,經常會遇到retain cycle的問題,例如:

1 - (void)dealloc

2 5 - (void)loadview

6 ];

16 }

在block中用到了self,self會被block retain,而_observer會copy乙份該block,就是說_observer間接持有self,同時當前的self也會retain_observer,最終導致self持有_observer,_observer持有self,形成retaincycle。

對於在block中的retain cycle,在2011 wwdc session #322 (objective-c advancements in depth)有乙個解決方案weak-strong dance,其實現如下:

1 - (void)dealloc

2 5 - (void)loadview

6 ];

18 }

在block中使用self之前先用乙個__weak變數引用self,導致block不會retain self,打破retain cycle,然後在block中使用wself之前先用__strong型別變數引用wself,以確保使用過程中不會dealloc。簡而言之就是推遲對self的retain,在使用時才進行retain。

(3)return乙個block

返回乙個block時,arc會自動將block加上autorelease,所以需要注意,如果執行過程中不能接受在runloop接受後才釋放block,就需要自己加入@autoreleasepool塊,但是測試發現64位ios/mac時,系統會自動在使用結束後立即釋放,32位則要等到runloop結束。

1 - (void)test

2 10 nslog(@」3」);

11 }

12 - (ibaction)ok:(id)sender

13

//執行結果

1釋放23釋放4 64位

123釋放4釋放 32位

12釋放釋放34 32位+@autoreleasepool

(4)block作為引數

block作為引數時,如果使用範圍超過了block的作用域(比如非同步時,或者將block傳遞給其他物件等等),則需要copy此block,copy建議在使用此block的方法內實現(誰使用,誰管理),而不是在傳遞引數時copy。注意,block過乙個strong型別的指標時,會自動copy。經過copy過的block會從棧空間移動到堆上,並且,copy乙個已經在堆上的block時,此block不會受影響。

引用計數和AddRef Release

addref和release實現的是一種名為引用計數的記憶體管理技術,這種技術是使元件能夠自己將自己刪除的最簡單同時也是效率最高的方法。com元件將維護乙個稱作是引用計數的數值。當客戶蟲元件取得乙個介面時,此數值增1,當客戶使用完某個介面後,此數值將減1。當此數值為0時,元件即可將自己從記憶體中刪除...

自動引用計數

每當你產生乙個物件,arc分配一大塊控制項去儲存這個物件。除此之外,當乙個物件是不在需要,arc 將會收回這個例項物件所佔的空間。如果乙個物件的空間被釋放掉,但是你任然通過物件的引用呼叫方法或者屬性,你的程式將要崩潰。為了不讓物件被釋放掉 arc將會追蹤有多少屬性 常量 變數正在引用這個物件。只要有...

引用計數 copy on write

拷貝通常分為值拷貝也叫淺拷貝和深拷貝,當拷貝方式為淺拷貝時就會有以下兩個問題 1 當需要調析構函式時,會出現同一塊空間被析構兩次的情況 2 如果是對指標的淺拷貝,會讓兩個指標同時管理同一塊空間,當乙個指針對這塊空間進行修改時,會影響到另外乙個指標。通過引用計數加寫時拷貝可以有效地解決這些問題。引用計...