標籤:style color io os 使用 ar strong for 檔案
基本原理:
1、什麼是記憶體管理 -》行動裝置的記憶體極其有限,每個app所能佔用的記憶體是有限制的 -》當app所佔用的記憶體比較多時,系統會發出記憶體警告,這時得回收一些不需要在使用的記憶體空間,比如回收一些不需要使用的對象、變數等 -》
管理範圍:任何繼承了NSObject的對象。對其他基礎資料型別 (Elementary Data Type)(int、char、float、double、struct、enum等)無效 局部變數都放在了記憶體中的棧空間中,對象放在堆空間中 堆空間中的東西是動態分配的,需要我們手動回收。棧空間不用我們自己管
2、對象的基本結構
每個OC對象都有自己的引用計數器,是一個整數,表示"對象被引用的次數",即有多少人正在使用這個OC對象。(分配4個位元組的儲存空間存放引用計數器)。當對象剛剛產生的時候引用計數器是1
3、引用計數器的作用 當使用alloc、new或者copy建立一個新對象時,新對象的引用計數器預設是1
當一個對象的引用計數器值為0是,對象佔用的記憶體就會被系統回收。換句話說,如果對象的計數器不為0,那麼在整個程式運行過程,它佔用的記憶體就不可能被回收,除非整個程式已經退出。
4、引用計數器的操作
-》給對象發送一條retain訊息,可以使引用計數器值 +1 (retain方法返回對象本身)
-》給對象發送一條release訊息,可以使引用計數器值 -1 (沒有傳回值)
-》可以給對象發送 retainCount訊息,獲得當前的引用計數器值 關閉ARC(Automatic Reference Counting): 選中項目名稱→Building Settings→Levels→Apple LLVM 6.0 -Language -Objective C將下面的YES改為no
NSUInteger:相當於long,輸出的時候預留位置使用%ld
殭屍對象:引用計數器變成0的對象,將不能使用,稱為殭屍對象
野指標:指向殭屍對象(不可用記憶體)的指標,給野指標發送訊息會報錯
null 指標:沒有指向任何東西的指標(儲存的東西是nil、NULL、0),給null 指標發送訊息不會報錯 錯誤:
EXC_BAD_ACCESS:訪問了一塊壞的記憶體(已經被回收、已經停用記憶體); 為了防止訪問壞記憶體的錯誤,我們可以在對象的計數器的值減為0之後,將指標賦空值
p=nil;//將指標p變成null 指標
OC中不存在null 指標錯誤,給null 指標發送訊息,不會報錯
-[Person setAge:]: message sent to deallocated instance 0x100202230
給已經釋放的對象發送了一條setAge:訊息
5、對象的銷毀 -》當一個對象的引用計數器值為0時,那麼他將被銷毀,其佔用的記憶體被系統回收 -》當一個對象被銷毀時,系統會自動向對象發送一條dealloc訊息 -》
一般會重寫dealloc方法,在這裡釋放相關資源,dealloc就像對象的遺言 -》
一旦重寫了dealloc方法,就必須調用[super dealloc],並且放在最後面調用 -》
不要直接調用dealloc方法 -》一旦對象被回收,它佔用的記憶體就不能再用,堅持使用會導致程式崩潰(野指標錯誤)
記憶體管理原則 對對象進行一次retain,那麼使用結束的時候就要release
誰建立,誰release。如果你通過alloc、new建立一個對象,那麼你必須調用release
誰retain,誰release。只要你調用了retain,無論這個對象是如何產生的,你都要調用release 你想使用(佔用)某個對象,就應該讓對象的計數器+1(讓對象做一次retain操作) 你不想再使用(佔用)某個對象,就應該讓對象的設計器-1(讓對象做一次release) 在類的實現中擷取成員變數值方法: _speed:直接存取成員變數 self->_speed:直接存取成員變數 self.speed:get方法 [self speed]:get方法
記憶體管理代碼規範:
1、只要調用了alloc,必須有release(aotorelease)
如果對象不是通過alloc產生的,就不需要release
2、set方法的代碼規範
-》基礎資料型別 (Elementary Data Type):直接賦值
- (void)setAge:(int)age
{
_age=age;
}
-》OC物件類型
- (void)setCar:(Car *)car
{
//1、判斷是不是新傳進來的對象
if(car != _car)
{
//2、對舊對象做一次release
[_car release];
//3、對新對象做一次retain
_car = [car retain];
}
}
3、dealloc方法的代碼規範
-》一定要[super dealloc],而且要放到最後面
-》對self(當前)所擁有的其他對象做一次release
- (void)dealloc
{
[_car release];
[super dealloc];
}
@property的記憶體管理
@property (retain) Book *book;
產生的set方法如下:
- (void)setBook:(Book *)book
{
if(_book != book)
{
[_book release];
_book = [book retain];
}
}
1、set方法記憶體管理相關參數:
retain :release舊值,retain新值(適用於OC物件類型)
assign:直接賦值(預設,適用於非OC物件類型)
copy :release舊值,copy新值
2、是否要產生set方法
readwrite:同時產生setter和getter的聲明、實現(預設)
readonly :只會產生getter的聲明、實現
3、多線程管理
nonatomic:產生set方法的時候不要加多線程代碼。效能高(一般就用這個)
atomic :產生set方法的時候加多線程代碼。效能低(預設)
4、setter和getter方法的名稱
setter:決定了set方法的名稱,一定要有一個冒號(不常用)
getter:決定了get方法的名稱
(一般用在BOOL類型)
@property int age;產生的方法名為:age,setAge:
@property (getter=abc , setter=setAbc: ) int age;
產生的方法名:get方法:abc
set方法:setAbc:
long表示時間類型的時候,是從1970-01-01 00:00:00開始,一共過了多少毫秒
循環參考:
涉及到循環參考(你中有我,我中有你),添加引用的時候使用@class 類名
1、@class的作用:僅僅告訴編譯器,某個名稱是一個類
@class Card;//僅僅是告訴編譯器,Card是一個類
2、開發中引用一個類的規範
-》在 .h 檔案中用@class來聲明類
-》在 .m 檔案中用#import來包含類的所有東西
使用@class可以提高編譯器編譯效率(當一個類被多個類引用的時候,如果類發生變化,那麼需要重新拷貝)
3、兩端循環參考解決方案:
-》一端用retain
-》一端用assign
autorelease:半自動釋放
@autoreleasepool
{//{ 開始代表建立了釋放池
Person *p = [[[Person alloc] init] autorelease];
p.age = 19;
}// }結束代表銷毀釋放池 注意:@autorelease是可以嵌套的,是以
棧(先進後出)的方式儲存的 1、autorelease的基本用法 -》會返回對象本身 -》會將對象放到一個自動釋放池中 -》當自動釋放池被銷毀時,會對池子裡面的所有對象做一次release操作 -》Person *p = [[[Person alloc] init] autorelease]; 調用完autorelease方法後,對象的計數器不變 2、autorelease的好處 -》不用在關心對象釋放的時間 -》不用再關係什麼時候調用release 3、autorelease的使用注意 -》佔用記憶體較大的對象不要隨便使用autorelease -》佔用記憶體較小的對象使用autorelease,沒有太大影響 4、錯誤寫法 -》alloc之後調用autorelease,有又調用release @autoreleasepool
{ Person *p = [[[Person alloc] init] autorelease];
[p release]; }-》連續調用多次autorelease @autoreleasepool { Person *p = [[[[Person alloc] init]
autorelease] autorelease]; }
5、自動釋放池 -》在IOS程式運行過程中,會建立無數個池子。這些池子都是以棧結果存在(先進後出) -》當一個對象調用autorelease方法時,會將這個對象放到棧頂的釋放池 6、自動釋放池的建立方式 -》IOS5.0前
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; Person *pp = [[[Person alloc] init] autorelease]; [pool release];
-》ios5.0開始 @autoreleasepool
{ Person *p = [[[[Person alloc] init] autorelease] autorelease]; }
1、系統內建的方法裡沒有包含alloc、new、copy,說明返回的對象都是autorelease的 NSString *str = @"13423";這種方式建立出來的字串對象,預設就是autorelease的。不需要我們去管理記憶體
2、開發中經常會提供一些類方法,快速建立一個已經autorelease過的對象
-》建立對象時不要直接使用類名,一般用self + (id)person
{ return [[[self alloc] init] autorelease];}
總結: 一、計數器的基本操作 retain:+1 release:-1 retainCount:獲得計數器 二、set方法的記憶體管理 -》set方法的實現
- (void)setCar:(Car *)car { if(_car != car) { [_car release]; _car = [car retain]; } }
-》dealloc方法的實現
- (void)dealloc { [_car release]; [super dealloc]; }
三、@property參數 -》OC對象 @property (nonatomic, retain) 類名 *屬性名稱; @property (nonatomic, retain) Car *car; @property (nonatomic,retain) id car;
被retain過的屬性,必須在dealloc方法中release屬性 -》非OC對象 @property (nonatomic,assign) 類型名稱 屬性名稱; @property (nonatomic,assign) int age; 四、autorelease -》系統內建的方法中,如果不包含alloc、new、copy,那麼這些方法返回的對象都已經autorelease過的 [NSString stringWithForm:.........] [NSDate date]; -》開發中經常寫一些類方法快速建立一個autorelease的對象 建立對象的時候不要直接使用類名,使用self
Objective-C:07_記憶體管理