這個也許是問得最多的問題了吧。全部這些問題每每來源於3個地方,一、不瞭解底層機制;二、沒有吃透規則; 三、不瞭解經常使用container的Reference Counting特性,或着說沒有下功夫去看對應文檔。 html
1. 底層機制 ios
你們是否知道從舊時代的MRC到ARC機制到底意味着什麼呢? 爲何ARC從開發速度,到執行速度和穩定性都要優於MRC?開發速度不言而喻,你少寫不少release代碼,甚至不多去操心這部分。執行速度呢?這個還要從runtime提及,還記得我在第2點說得一句話麼:「Runtime is everything between your each function call.」 程序員
MRC是一個古老的內存管理哲學,誰分配誰釋放。經過counting來計數到底該資源有幾個使用者。道理很簡單,可是每每簡單的東西人卻會犯錯。歷來沒有一個程序員能夠充滿信心的說,我寫得代碼歷來沒有過內存泄露。這樣來看,咱們就更須要讓程序能夠本身處理這個管理機制,這就須要把這個機制放到runtime裏。 算法
因此MRC->ARC就是把內存管理部分從普通開發者的函數中移到了函數外的runtime中。由於runtime的開發原型簡單,邏輯層次更高,因此作這個開發和管理出錯的機率更小。實際上編譯器開發人員對這部分通過無數次測試,因此能夠說用ARC幾乎不會出錯。另外因爲編譯的額外優化,使得這個部分比程序員本身寫得代碼要快速不少。並且對於一些通用的開發模式,例如autorelease對象,ARC有更優秀的算法保證autoreleasepool裏的對象更少。 app
2. RC規則 函數
首先說一下RC是什麼,r-Reference參照,引用 c-counting計數, RC就是引用計數。俗話說就是記錄使用者的數量。 例如如今我有一個房間空着,你們能夠進去隨意使用,可是你進門前,須要給門口的計數牌子+1,
出門時候-1。 這時候這個門口的牌子就是該房間裏的人數。一但這個牌子變爲0我就能夠把房間關閉。 測試
這個規則可讓NSObject決定是否是要釋放內存。當一個對象alloc時候,系統分配其一塊內存而且object自動計數retainCount=1 這時候每當[object retain]一次retainCount+1(這裏雖然簡寫也是rc不過是巧合或者當時開發人員故意選的retain這個詞吧)每次[object release]時候retainCount-1 當retainCount==0時候object就真正把這快內存還給系統。 優化
3. 經常使用container的Reference Counting特性 ui
這個規則很簡單把。可是這塊確實讓新手最頭疼的地方。問題出在,新手總想去驗證RC規則,又老是發現和本身的指望不符合。無數次看到有人寫下以下句子 this
NSLog(@"%d",[object retainCount]); while([object retainCount]>0){ [object release]; }
固然了,我也作過相似的動做,那種但願一切盡在掌握中的心態。可是你會看到其餘人告訴這麼作徹底沒有意義。rc does not work this way. 也許這樣的暴力釋放會起做用,可是retainCount並非用來作這個的。每一個數字意味着有其它對象引用該資源,這樣的暴力釋放很容易致使程序崩潰。這個數字也許並非你心目中的哪一個。由於你很難跟蹤到底哪些對象引用的該資源。你用代碼創建的資源不光只有你的代碼纔會用到,你調用的各類Framework,Framework調用的Framework,都有可能改變這個資源的retainCount.
因此去驗證RC規則不是明智之舉。你能作的就是理解規則,使用規則,讀文檔瞭解container的引用特性。或者乾脆移到ARC上面,讓runtime環境處理這些問題。最後說一下不用arc的狀況。目前狀況來看,有很多第三方的庫並未支持ARC,因此若是你的舊項目使用了這些庫,請檢查是否做者發佈了新版本,或者你須要本身修正支持ARC。
最後補充記錄下ARC的新規則(ARC Enforces New Rules):
爲了正常運轉,ARC使用了一些在使用其它編譯模式下沒有的新規則。這些規則意在提供徹底可靠的內存管理模型;在某些狀況下,它們僅使用最佳實踐方法,在其它狀況下,它們僅簡化你的代碼或明顯的作出推論告知你不須要處理內存管理。若是你違反了這些規則,你會立刻獲得一個編譯期錯誤,而不是在運行期可能會顯現的一個狡猾的bug。 // Won't work: @property NSString *newTitle; // Works: @property (getter=theNewTitle) NSString *newTitle; |