天天看點

iOS的block記憶體管理

初始情況下:

block本身、__block修飾的變量以及在block内部使用的變量都是在棧裡的。

__block修飾的變量的位址會作為實參傳入block塊内部(暫時先這麼了解,實際比較複雜)。block使用的外部變量被const拷貝到了block内部。也就是block使用的外部變量和這個外部變量本身沒有關系。

copy方法之後

被拷貝的方法還是在棧上。但是拷貝之後的block已經被放在了heap(堆)上。同時__block修飾的變量被移動到了堆上,原來在棧上的已經不存在。還有block的外部變量的const拷貝也被拷貝到了堆上。

如果block塊使用的外部變量是一個refernce的對象,那麼這個對象的引用計數會增加1。

堆上的block再做一次copy之後,隻是引用計數增加1,但是不會重新再做拷貝動作。

retain操作

由于retain是有傳回值的。retain要求傳回的位址和調用對象的位址一緻。但是block的位址可能是會變的(尤其是從棧到堆的過程),是以對block做retain操作是沒有用處的。什麼都不會做!

銷毀(或記憶體回收時)

heap上的block塊先于stack上的被銷毀時,如調用release銷毀堆上的block塊。heap中的block塊在引用計數變為0的時候被銷毀。而__block修飾的變量還在heap中,因為stack還要使用,同時棧上的block快也要使用。

當heap上的block塊晚于stack時,stack會被清除。在heap中的block塊在調用release減少引用計數到0的時候釋放記憶體。

block和objective-c對象

如果對block做拷貝操作,block會對其内部使用的對象生成強引用。

如果在block塊内部使用了:

以引用的方式使用了類的成員變量,那麼這個block會對self産生強引用。

以值得方式使用了類的成員變量,那麼這個block會對這個變量本身産生強引用。

例如:

iOS的block記憶體管理
iOS的block記憶體管理

以上可以通過__block修飾符來改變。是的__block是另外的一種存儲類型,就像copy、retain什麼的。這樣這個引用就直接被傳遞到了block中。

但是__block是不可以用來消除對self的循環引用的。

歡迎加群互相學習,共同進步。qq群:ios: 58099570 | android: 330987132 | go:217696290 | python:336880185 | 做人要厚道,轉載請注明出處!http://www.cnblogs.com/sunshine-anycall/p/4780356.html

繼續閱讀