標籤:
記憶體管理 1、基本知識 2、關閉ARC機制 3、@property 4、循環參考 5、自動釋放池
一、基本知識
記憶體的分類
棧:局部變數
堆:動態申請的對象,變數等
全域(靜態):static 變數,const變數,全域變數等
引用計數器
每個OC對象都有自己的引用計數器,是一個整數,表示“對象被引用的次數”,即有多少人正在使用這個OC對象
每個OC對象內部專門有4個位元組的儲存空間來儲存引用計數器
作用
當使用alloc、new或者copy建立一個新對象時,新對象的引用計數器預設就是1
當一個對象的引用計數器值為0時,對象佔用的記憶體就會被系統回收。換句話說,如果對象的計數器不為0,那麼在整個程式運行過程,
它佔用的記憶體就不可能被回收,除非整個程式已經退出。
引用計數器的操作
1、給對象發送一條retain訊息,可以使引用計數器值+1(retain方法返回對象本身)
2、給對象發送一條release訊息,可以使引用計數器值-1
3、可以給對象發送retainCount訊息獲得當前的引用計數器值
總結:有始有終,有加有減。
二、關閉ARC機制
如果要自己調用release等函數,需要關閉ARC功能,關閉方法參考
http://jingyan.baidu.com/article/358570f67babbcce4724fcd8.html
管理方式set方法加1,dealloc 減1
1、想使用某個對象,就應該讓對象的計數器加1(retain)
2、不想再使用某個對象時,就應該讓對象的計數器減1 (release)
2、誰retain誰release,誰alloc誰release
記憶體管理規範:
1、只要調用alloc必須有release,如果不是alloc那就不需要release
2、set 方法
基礎資料型別 (Elementary Data Type)直接賦值
OC物件類型。
先判斷是不是同一個對象 if(car != _car)。
然後對舊對象release,對新車進行一次retain操作。
3、dealloc
一定要調用[super dealloc],而且放到最後邊
一定要當前對象release一次
三、@property
@property // 預設是賦值,retain 參數實現記憶體管理
@property int age; // 預設是賦值@property(retain) Book * book; // retain 參數實現記憶體管理
記憶體管理總結:
1、記憶體管理的相關參數
retain :release舊值,retain新值
assign :直接賦值,預設就是這個,適用於非OC物件類型
copy :release舊值,copy新值
2、是否要產生set方法
@property (readonly) int age; // 唯讀,只產生getter方法
@property (readwrite) int name; // 讀寫,預設是讀寫
3、多線程管理
nonautomic : 效能高,
automic : 效能低(預設)
@property (nonautomic , assign) int age; // 以後這樣寫
4、setter和getter方法的名稱
@property (setter = myAge:) int age; // setter = set方法名 ,自訂setter方法名,不要忘記冒號
@property (getter = getAge) int age; // getter = get方法名 ,自訂getter方法名
@property (getter = isRich) BOOL rich; // 一般這個會用在BOOL類型的變數聲明,getter方法名以is開頭
四、循環參考
類A引用類B,類B引用類A。
解決方案: @class A;// 僅僅告訴編譯器A是一個類
在類引用前,在聲明檔案裡使用關鍵字@class A;
@class 和#import區別
1、#import方式會包含被引用類的所有資訊,包括被引用類的變數和方法;@class方式只是告訴編譯器在A.h檔案中 B *b 只是類的聲明,具體這個類裡有什麼資訊,這裡不需要知道,等實現檔案中真正要用到時,才會真正去查看B類中資訊
2、如果有上百個標頭檔都#import了同一個檔案,或者這些檔案依次被#improt,那麼一旦最開始的標頭檔稍有改動,後面引用到這個檔案的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了
3、在.m實現檔案中,如果需要引用到被引用類的實體變數或者方法時,還需要使用#import方式引入被引用類
在開發中引用一個類的規範
1、在.h檔案中用@class來聲明類
2、 在.m檔案中用#import 來包含類的所有東西
3、 迴圈retain的解決方案
一端用retain,一端用assign
五、自動釋放池
autorelease 基本用法
1、會將對象放到一個自動釋放池中
2、當對象釋放池被銷毀時,會自動釋放裡面的所有對象(release操作)
3、會返回對象自身
4、調用autorelease後,對象的計數器不變
好處
1、不用再關心對象釋放的時間
2、不用再關心什麼時候調用release
注意事項
1、佔用記憶體較大的對象不要隨便使用autorelease
2、佔用記憶體較小的使用autorelease,沒有太大影響
3、autorelease和release一樣,也是和alloc/new/copy一一對應
1 @autoreleasepool // 自動釋放池 2 { 3 Person *p = [[[Person alloc] init] autorelease]; // autorelaese 方法返回對象本身,計數器並不會立即改變 4 Card *c = [[[Card alloc] init] autorelease]; 5 6 p.card = c; 7 c.person = p; 8 9 @autoreleasepool // 可以嵌套10 {11 12 Person *p = [[[Person alloc] init] autorelease];13 Card *c = [[[Card alloc] init] autorelease];14 15 16 p.card = c;17 c.person = p;18 19 20 }21 22 }
IOS開發學習筆記013-記憶體管理