iOS 內(nèi)存管理

前言

現(xiàn)在iOS 開發(fā)已經(jīng)不再是 mrc 了,現(xiàn)在是 arc 和 swift 的時代,但是內(nèi)存管理一直是個非常重要的問題,對于我們初學者來說,如果只是盲目的開發(fā),不知道管理內(nèi)存的話,會給我們的開發(fā)帶來很大的麻煩。
  內(nèi)存管理是程序開發(fā)中很重要的一部分,我們的程序在運行中會消耗內(nèi)存,運行結束之后釋放占用的內(nèi)存。如果在程序運行中只占用內(nèi)存不及時釋放的話,會導致程序的內(nèi)存越來越少,最終導致程序崩潰。所以,作為我們程序員,在開發(fā)的過程中一定要處理好內(nèi)存問題。


首先,我們先了解下內(nèi)存管理中相關的概念:

1.引用計數(shù)

在 ObjC中,創(chuàng)建的對象什么時候會被釋放?
  當這個對象沒有被任何變量引用的時候,或者說沒有指針指向的時候,這個對象就會被釋放。
  我們怎么才能知道對象有沒有被引用呢?
  引用計數(shù):
  1.每個對象都會關聯(lián)一個整數(shù),這個整數(shù)就叫做引用計數(shù)器
  2.對象每創(chuàng)建一次,其引用計數(shù)就會加1
  3.當對象銷毀的時候,其引用計數(shù)減
  4.當對象的引用計數(shù)為0的時候,會給對象發(fā)送 dealloc 消息銷毀對象:由于釋放對象會調(diào)用 dealloc 方法,因此要重寫 dealloc 方法來查看對象是否釋放了。

2自動釋放池

從前面我們已經(jīng)知道了,當一個對象不再使用的時候,會被釋放掉,但是有些時候,我們不知道對象什么時候不再使用,不能確定被銷毀的時間。
  ObjC給我們提供了 autorelease 的方法來解決這個問題,當給一個對象發(fā)送 autorelease 消息的時候,方法就會在未來的某個時間里給這個對象發(fā)送 release 消息,來釋放該對象。
  什么是自動釋放池呢?
  自動釋放池就是一個可以容納對象,并且可以自動釋放對象的一個池子,方便了我們對內(nèi)存的管理。
  它的原理就是在對象接到autorelease的時候,會被添加到當前的自動釋放池中,當這個自動釋放池銷毀額時候,會給池中所有的對象發(fā)送 release 消息,銷毀對象 。


3 iOS的內(nèi)存管理原則

3.1基本原則
  1.當我們通過 new、alloc、copy 方法創(chuàng)建一個對象的時候,它的引用計數(shù)為1,當我們不再使用該對象的時候,應該向對象發(fā)送 release 或者 autorelease 消息來釋放對象。
  2.當我們通過其他方法獲得一個對象的時候,如果對象的引用計數(shù)為1且被設置為autorelease,那么就不需要執(zhí)行任何釋放對象的操作;
  3.如果你打算取得對象額所有權,就需要保留對象并在操作完成之后釋放,保證相等次數(shù)的 retain 和 release。
其實就是有借必有還
  3.2 ARC
  在 MRC 時代,我們必須要遵守上面的規(guī)則,如果不遵守的話內(nèi)存問題將會很讓人頭疼,但是到了ARC 的時代,內(nèi)存問題就相對于之前沒那么復雜了,對于初學者來說就能更好的來管理內(nèi)存問題。
  iOS 5之后,我們就可以開啟 ARC 模式了,你可以將它理解為一個助手,它會幫我們管理內(nèi)存,不需要我們手動的添加了,它的工作原理就是編譯器在編譯的時候會在代碼中插入合適的 retain 和 release 語句,就相當于在背后幫我們完成了內(nèi)存的管理工作。
  注意:
  1.如果你的工程是老工程的話。你可以轉換成 ARC,這樣可以方便后期的維護。
  2.如果你的工程引用了一些不支持ARC 的庫,可以在Build Phases的Compile Sources將對應的m文件的編譯器參數(shù)配置為-fno-objc-arc
  3.3 ARC 的修飾符
  ARC 模式下一共有四種修飾符,分別是strong、weak、autoreleasing、unsafe_unretained
  strong:強引用,持有所指向對象的所有權,無修飾符的情況下,默認就是 strong,如果想要強制性釋放,將對象置為 nil。
  weak:弱引用,不持有所指向對象的所有權,指向的對象內(nèi)存被銷毀之后,引用本身會置為 nil,這樣可以避免野指針。比如我們?yōu)榱吮苊庋h(huán)引用,聲明的時候要用 weak。
  autoreleasing:自動釋放對象的引用,一般用于參數(shù)的傳遞。
  unsafe_unretained:這個修飾符是在 iOS5之前用的,相當于現(xiàn)在 weak,現(xiàn)在一般都用不到了。
  3.4 屬性的內(nèi)存管理
  1.assign:直接賦值
  assign 一般用來修飾基本數(shù)據(jù)類型,它也可以修飾 OC 對象,但是不推薦這樣寫,因為被 assign 修飾的對象釋放之后,指針還是指向釋放前的內(nèi)存,容易導致程序崩潰。
  2.retain
  retain 和 strong 一樣,都是用來修飾 OC 對象的
  使用 set 方法賦值的時候,實際上是會先保留新值,再釋放舊值,在設置新值,避免新舊值一樣時導致對象被釋放的問題
  MRC

- (void)setCount(NSObject*)count { 
         [count retain]; 
         [_count release];
         _count = count;
 }
  ```
  ARC
  • (void)setCount:(NSObiect *)count {
    _count = count;
    }
  **3.copy**
  一般是用來修飾 String、Dict、Array 的,尤其是在內(nèi)容可變的情況下,會深拷貝一份內(nèi)容給屬性,避免可能造成對源內(nèi)容進行改動。
  **4.weak**
   weak 和 strong 一樣都是用來修飾 OC 對象的,比如常用代理的聲明,Xib 控件的引用都是用的 weak。
  **3.5 block 內(nèi)存管理**
  iOS 中使用 block 必須要自己管理內(nèi)存,錯誤的內(nèi)存管理將導致循環(huán)引用等內(nèi)存泄漏問題,只用 block 時候要注意以下幾點:
  1.當你聲明一個block 時候,要使用 copy 來修飾,不要用 retain 來修飾。
  2.block 會對內(nèi)部使用的對象進行強引用,可以給其添加一個弱引用的標記。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容