在之前的一片文章我們說了OC中謂詞操作:http://blog.csdn.net/jiangwei0910410003/article/details/41923507,從今天開始我們就來看一下OC中最難的一部分內容:內存管理
為什么說他難呢?因為內存如果需要我們程序員去管理的話,那個難度肯定是很大的,如果是Java,垃圾回收器會把這份工作給做了,我們不需要關心,但是就是因為如此,Android運行速度上會慢一下,原因很簡單,Java的垃圾回收器有很多收集算法的,這個在回收的過程中是很浪費時間的,效率自然就低了,但是如果這份工作給程序員自己去做的話,效率上肯定會增加,但是對於程序員來說任務就比較繁重了,而且還要特別的小心,千萬不能造成內存溢出和泄露。
這里我們主要從四個方面來介紹一下內存管理
1、簡單的例子來了解引用計數的使用
2、set方法來控制引用計數問題
3、銷毀方法來控制引用計數問題
4、初始化方法來控制引用計數問題
下面就來簡單看一下OC中的內存管理
這個例子有點復雜,我們慢慢分析
Dog.h
Dog類中定義了name屬性,並且給他提供了一個set方法
Person.h
Person類中有一個Dog的屬性,然后提供了set方法。代碼有點復雜,我們后面會詳細說明
下面來看一下測試代碼
main.m
首先如果想演示這個例子的話,需要修改一下設置:
最新的XCode默認是會自動選上ARC(Automatic Reference Counting),如果我們不把這個手動關閉的話,代碼中會報錯的。
alloc用來創建對象,創建完成之后,引用計數為1,只調用一次
retain使引用計數+1,可以多調用幾次
release使引用計數-1,可以多調用幾次
當引用計數為0的時候會調用dealloc
黃金法則:每次調用alloc一次,都需要調用release一次,他們兩是成對出現的
最新的Xcode版本默認情況下會開啟ARC機制的,當開啟這個機制之后,我們就不能手動的顯示調用這些方法,編譯器會報錯
所以我們可以將這個默認狀態的ARC關閉,但是這個只是為了測試使用
同時我們會發現main.m文件中沒有自動釋放池了@autoreleasepool了。
1、簡單的例子
我們創建了一個Person類,然后可以打印一下的引用計數值:1
當我們調用retain方法的時候,引用計數就會+1,當我們調用release方法的時候引用計數會-1
一旦系統發現引用計數為0的時候,就會銷毀這個對象,調用dealloc方法
2、set方法來控制引用計數
這個例子簡單吧,沒什么問題的,現在我們把問題復雜化
我們定義了兩條狗,然后將這兩條狗通過setDog方法設置到p1對象上,同時將第一條狗設置到p2對象上,這時候我們打印一下第一條狗的引用計數,發現他的引用計數是1,原因很簡單,這個1是在alloc時候有的,但是現在是有問題的,因為第一條狗被p1和p2引用者,按照正常情況,第一條狗的引用計數為3的。所以這時候我們就需要修改一下Person類中setDog方法了
我們需要手動的增加dog的引用計數,這樣就正常了。
現在又有一個問題了,上面p1對象設置了第二條狗
按照上面的setDog方法,我們又發現一個問題,現在p1引用的狗是第二條狗了,不是第一條,那么這時候按照正常情況第一條狗的引用計數-1,因為他已經不再被p1引用了。所以setDog方法還得修改:
這時候我們就在賦值之前,對_dog調用一次release方法,這樣就解決了上面的那個問題。
但是現在還有一個問題:
在執行release代碼之后,dog1的引用計數為1,這是繼續調用setDog方法:
這時候_dog是dog1,繼續調用release方法,執行完之后,引用繼續為0了,對象被釋放了,但是這時候dog參數的值還是dog1,那么在執行retain方法就會報錯了,這個原因很簡單,就是我們兩次調用了setDog方法,將dog1設置了兩次。中間調用一次release方法。所以解決這樣的問題,我們在修改一下setDog方法:
我只需要判斷一下,之前的屬性值和當前需要設置的值是否相同。這種方式就是沒有問題了,所以我們以后在寫set方法的時候,這就是模板了。
3、銷毀方法dealloc控制引用計數
現在假如p1被銷毀了,那么對於dog1來說引用計數應該-1的,所以需要在Person類中的dealloc方法中修改一下:
4、初始化方法控制引用計數
現在還有一種情況,如果我們使用初始化方法來設置Dog屬性值:我們這里的處理和setDog方法的處理方式一樣,但是這里不需要做一次判斷了,因為初始化方法只會調用一次。所以不會出現setDog的第三種情況。
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。