iOS記憶體管理 講的不錯,角度獨特

2021-09-06 15:11:19 字數 2597 閱讀 6065

ios的記憶體管理,包括物件的所有權與引用計數、自動釋放、訪問器方法與屬性、一些會改變引用計數的特殊情況   

----- 物件所有權(ownership) 與引用計數 (retain count 、reference count)

當乙個所有者(owner,其本身可以是任何乙個objective-c物件)做了以下某個動作時,它擁有對乙個物件的所有權(ownership)

1、建立乙個物件,包括使用任何名稱中包含 "alloc"   "new"  "copy"的方法

2、保留(retain)乙個物件

乙個物件可以有多個所有者,乙個所有者也可以擁有多個物件

相應的,引用計數增減的基本規則是:

1、當所有者建立乙個物件時,該物件的引用計數為1

2、當所有者保留它時,該物件的引用計數加1

3、當所有者釋放(release)它時,該物件的引用計數減1

當乙個所有者對於乙個物件的引用計數的增減總計為0時,它放棄了對這個物件的所有權

從兩個不同的角度來看記憶體問題。

1、當乙個物件有著至少乙個所有者(owner)的時候,它依然存在;當它沒有任何所有者的時候,它會被釋放掉

2、從引用計數的角度看,乙個物件存在時,其引用計數大於0,當乙個物件的引用計數為0時,它會呼叫dealloc方法並釋放掉

兩者的關係是:在所有權的背後起作用的機制是引用計數機制。我們只應當使用所有權的概念來管理記憶體,因為如果試圖直接獲取物件的引用計數,那麼得到的數字會匪夷所思 -- 系統的一些框架會「偷偷」增減物件的引用計數

記憶體管理的目標:

當乙個物件的某個所有者依然需要使用它時,保證這個物件的存在;當乙個物件的所有者不再需要它時,保證這個物件被銷毀。因此只要任何乙個所有者在使用完乙個物件之後釋放掉它,那麼記憶體管理的目標就可以實現。

任何乙個所有者(所有者本身也只是乙個物件)所應當遵守的基本步驟:擁有乙個物件 -> 使用乙個物件  -> 放棄物件的所有權

從引用計數的角度來看:還需要這個物件時,保持對其增減為正;不再需要這個物件時,保持對其增減為0

下圖,所有者1和所有者2單獨地執行了擁有物件、使用物件、放棄物件所有權的步驟;當所有者1不再需要該物件時及時放棄了所有權,但此時所有者2依然擁有該物件,因此該物件依然存在,所有者2可以繼續使用它;當2也不再需要該物件時,也放棄掉所有權;這時物件不再有任何所有者,因此立刻被銷毀掉

所有者2只是複製了該物件的指標,並沒有使用copy方法,因此複製指標這個操作本身並不增加物件的引用計數;因為所有者2希望能使用該物件,因此通過retain方法成為它的所有者,也保證了所有者1放棄該物件時,物件不被銷毀。

右手邊前兩個步驟的**實現應該為   if(obj1 != obj)

有時候乙個所有者建立乙個物件後,會立刻將該物件的指標傳遞給其他所有者,這時,這個建立者不希望再擁有這個物件,如果立刻給它乙個release,會導致這個物件被立刻被釋放掉,這樣其他所有者還沒來得及保留該物件,解決這個問題的方法是,給物件傳送乙個autorelease訊息:這樣建立者不再擁有該物件的所有權:該物件成為自動釋放的物件,但不會立刻被釋放掉,其他所有者可以有時間保留或者賦值該物件,並成為其唯一所有者。

看乙個自動釋放的demo,一所有者先用alloc方法建立乙個物件,此時該所有者擁有了這個物件,物件的引用計數為1.接著,所有者自動釋放該物件,所有者此時已經放棄了所有權,但物件的引用計數在一段時間內依然為1. 此時可以看出自動釋放的另乙個好處,不會因為忘記給物件傳送release 而造成記憶體洩露。

-(object *)returnautoreleaeobject

與自動釋放相關的,有一大類構造方法,由它們構造的物件直接就是自動釋放的物件,這一類哦鼓譟方法叫便捷方法,比如stringwithformat , nsarray 的arraywithobjects:和 arraywitharray:,uiimage的imagenamed:,nsnumber的numberwithbool等,autoreleae方法會在一段時間以後釋放掉乙個物件,在這段時間內我們可以安全地使用該物件,這段時間是多久呢?

先看看自動釋放池,其是nsautoreleasepool的例項,包含了收到autorelease訊息的物件,當乙個自動釋放池自身被銷毀(dealloc)時,它會給池中每乙個物件傳送乙個realeae訊息,乙個自動釋放的物件,至少能夠存活到自動釋放池銷毀的時候。

自動釋放池在每乙個時間週期(event cycle)的開始,系統會子弟哦那個建立乙個,在每乙個事件週期的末尾,系統會自動銷毀。可這樣理解:當**在持續執行時,自動釋放池是不會被銷毀的,此時可以安全的使用自動釋放的物件,當**執行告一段落,開始等待使用者輸入或者其他事件時,自動釋放池就被自動釋放掉,池中的物件都會收到乙個release訊息。

自動釋放而非直接釋放,可以幫助節省一些**量,提供開發速度,但有乙個直接的缺點:延緩了物件的釋放,在有大量自動釋放物件的時候,會占用大量記憶體資源,因此,需要避免大量物件自動釋放。

在以下情況,需要手動建立並手動銷毀自動釋放池:

1、當在主線程外開啟其他執行緒時:系統只會在主線程自動生成並銷毀掉自動釋放池

2、擋在短時間內製造了大量自動釋放物件時:及時地銷毀有助於有效利用手機上的記憶體資源

iOS的記憶體管理

今晚有空,總結一下學習ios記憶體管理的一些認識。文章中可能會涉及一些相對底層的知識,c的記憶體管理知識,慎入。前方高能!前方高能!前方高能!經典的記憶體劃分 棧 堆 bss段 資料段 段。如 下圖 先說堆疊 在c語言裡,可以簡單的說malloc等方法主動申請記憶體,其記憶體空間是在堆上,其他的在棧...

iOS的記憶體管理

通過字面的方式建立出來的物件儲存在常量區,通過物件方法和類方法建立出來的物件儲存在堆區 記憶體有系統管理,區域性變數儲存在棧,當變數離開其所在 快就會被 堆記憶體需要程式設計師自己管理,oc中的物件儲存在堆中 記憶體管理不當會造成的兩個問題 記憶體洩露,不再需要的物件沒有釋放,導致記憶體洩露,記憶體...

iOS的block記憶體管理

初始情況下 block本身 block修飾的變數以及在block內部使用的變數都是在棧裡的。block修飾的變數的位址會作為實參傳入block塊內部 暫時先這麼理解,實際比較複雜 block使用的外部變數被const拷貝到了block內部。也就是block使用的外部變數和這個外部變數本身沒有關係。c...