ARC中block块作为属性的使用笔记
ARC中block塊作為屬性的使用筆記
block較難理解,根據(jù)在內(nèi)存中的分布情況就分為3種類型,根據(jù)使用的情形又分為很多很多種。雖然用起來容易,但使用不當(dāng)會造成內(nèi)存泄露,雖然都是這么說,但你真的研究過為什么會泄露嗎?為什么有些時候外部變量進(jìn)入block的時候會導(dǎo)致引用計數(shù)+1呢?
?
本人做過MRC以及ARC的開發(fā),但大勢所趨,ARC將是以后開發(fā)的主要模式,即使有MRC也是ARC混編MRC的代碼,所以,本文的block的一些使用上的心得都基于ARC的,已經(jīng)不考慮MRC的了,請看官注意,MRC與ARC的block是有著很多很多區(qū)別的。
?
注意,以下心得是我自己長時間收集資料以及自己驗證所的出來的一些技巧與結(jié)論,不代表它的正確性,這僅僅是筆記,取舍由你決定,最好自己驗證一下。
首先建立出如下形式的工程,CV1 push 到CV2的這種形式。
它們的強(qiáng)引用關(guān)系如下:
以下是CV2的代碼,注意,要將block定義成copy屬性。
block被copy了有著什么現(xiàn)象發(fā)生呢?引用一段原文。
http://stackoverflow.com/questions/16149653/what-is-the-role-of-the-copy-in-the-arc
Blocks are similar to other objects for memory management, but not the same. When a block which accesses local variables is created, it is created on the stack. This means that it is only valid as long as its scope exists. To save this block for later, you must copy it, which copies it to the heap.
Blocks與其他對象的內(nèi)存管理相似,但又有著不同。當(dāng)一個block(block當(dāng)中有著外部變量進(jìn)入)被創(chuàng)建了,它是在堆區(qū)中的。那意味著,當(dāng)block中的代碼執(zhí)行完畢之后,這段代碼就再也不合法了,會被清除掉。為了讓這個block存活時間更久。你必須copy,將它拷貝到棧區(qū)。
1. CV1 push 到CV2,CV2在棧區(qū)里面,CV2 pop 掉后整個控制器都被釋放。
2. 作為屬性的block被copy之后會出現(xiàn)在CV2棧區(qū)里面,為什么在棧區(qū)里面,很簡單,它要隨著CV2的生命周期一致,CV2 pop 掉后這個block也會跟著一起消失的。
他們的強(qiáng)引用關(guān)系如下圖所示:
以下情形叫做有外部變量進(jìn)入block的情形,其中的self.name就是控制器CV2的一個屬性,對于block來講屬于外部變量。
這里有一個問題,對于進(jìn)入到block里面的外部變量,為什么會被block強(qiáng)引用呢?
我們可以這么想,block塊中的代碼并不是馬上就會執(zhí)行的,需要你手動調(diào)用才行,如上例中的self.oneBlock(@“YouXianMing”);有時候,這個方法都執(zhí)行結(jié)束了,這個block還沒有執(zhí)行,如果block中的對象沒有被block強(qiáng)引用,很有可能那個變量已經(jīng)消失了卻還調(diào)用了block,直接后果就是崩潰。為了保證block至少能用上一次,它必須強(qiáng)引用進(jìn)入到里面的外部變量。
所以上圖中的強(qiáng)引用關(guān)系圖如下所示:
如果CV2 pop 了,其釋放過程是這樣子的:
CV2被CV1強(qiáng)引用消失,CV2就會挨個檢查強(qiáng)引用,如果沒有發(fā)現(xiàn)自己被什么強(qiáng)引用,就會把所有的內(nèi)容清除掉,就是上圖中的oneBlock以及name。
最后,之后輪到oneBlock了,它也會解除name的強(qiáng)引用關(guān)系:
至此,都是很完美的,沒有內(nèi)存泄露什么的。
我們把代碼修改成如下的形式,我們在block中執(zhí)行一個方法,讓控制器執(zhí)行一個方法,即[self ......];
它們的強(qiáng)引用關(guān)系圖如下,注意下圖中的藍(lán)色的線條,因為外部變量self(CV2自身)傳了進(jìn)來,只出現(xiàn)的self也算傳進(jìn)來了哦。
這個時候,你如果將 CV2 pop掉。它們的關(guān)系圖如下所示:
這個時候,CV2會檢測自己有沒有被強(qiáng)引用,結(jié)果發(fā)現(xiàn)被一個對象oneBlock強(qiáng)引用了,那么它自身就不會被釋放掉,整個CV2都泄露了呢,泄露的原因就是循環(huán)引用。
這時候,你再從CV1 push 出CV2,以下是關(guān)系圖:
再次pop又會泄露一個CV2。每次的push與pop都會導(dǎo)致一個新的CV2整體被泄露哦。
?
這還只是作為屬性的block。其他的還沒講呢。作為屬性的block是最容易出現(xiàn)循環(huán)引用事件的。block的知識都比較隱晦,你以為你懂了,其實你沒懂。需要抱著一顆不浮躁的心,慢慢的分析它的特性,寫代碼驗證自己的想法,然后才會使用得得心應(yīng)手。
?
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的ARC中block块作为属性的使用笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模板插件aTpl.js新增功能
- 下一篇: 聚焦“裂变”,又拍云推出直播云等多场景解