1.方法的基本使用多線程
1> retain :計數器+1,會返回對象自己app
2> release :計數器-1,沒有返回值性能
3> retainCount :獲取當前的計數器atom
4> deallocspa
* 當一個對象要被回收的時候,就會調用線程
* 必定要調用[super dealloc],這句調用要放在最後面 3d
2.概念指針
1> 殭屍對象 :所佔用內存已經被回收的對象,殭屍對象不能再使用調試
2> 野指針 :指向殭屍對象(不可用內存)的指針,給野指針發送消息會報錯(EXC_BAD_ACCESS)代碼規範
3> 空指針 :沒有指向任何東西的指針(存儲的東西是nil、NULL、0),給空指針發送消息不會報錯
3.原則
1>.你想使用(佔用)某個對象,就應該讓對象的計數器+1(讓對象作一次retain操做)
2>.你不想再使用(佔用)某個對象,就應該讓對象的計數器-1(讓對象作一次release)
3>.誰retain,誰release
4>.誰alloc,誰release
1.只要調用了alloc,必須有release(autorelease)
對象不是經過alloc產生的,就不須要release
2.set方法的代碼規範
1> 基本數據類型:直接複製 - (void)setAge:(int)age { _age = age; } 2> OC對象類型 - (void)setCar:(Car *)car { // 1.先判斷是否是新傳進來對象 if ( car != _car ) { // 2.對舊對象作一次release [_car release]; // 3.對新對象作一次retain _car = [car retain]; } }
3.dealloc方法的代碼規範
1> 必定要[super dealloc],並且放到最後面 2> 對self(當前)所擁有的其餘對象作一次release - (void)dealloc { [_car release]; [super dealloc]; }
要想手動調用retain、release等方法,在建立項目的時候不要勾選ARC
默認狀況下,Xcode是不會管殭屍對象的,使用一塊被釋放的內存也不會報錯。爲了方便調試,應該開啓殭屍對象監控
@property (retain) Book *book;
@property (retain) NSString *name;
* retain : release舊值,retain新值(適用於OC對象類型)
* assign : 直接賦值,不作任何內存管理(默認,適用於非OC對象類型)
* copy : release舊值,copy新值通常用於NSString *)
* readwrite : 同時生成setter和getter的聲明、實現(默認)
* readonly : 只會生成getter的聲明、實現
* nonatomic : 性能高 (通常就用這個)
* atomic : 性能低(默認)
* setter : 決定了set方法的名稱,必定要有個冒號 :
* getter : 決定了get方法的名稱(通常用在BOOL類型)
// 返回BOOL類型的方法名通常以is開頭 @property (getter = isRich) BOOL rich; @property (nonatomic, assign, readwrite) int weight; @property (readwrite, assign) int height; @property (nonatomic, assign) int age; @property (retain) NSString *name;
對於循環依賴關係來講,比方A類引用B類,同時B類也引用A類,這種代碼編譯會報錯。當使用@class在兩個類相互聲明,就不會出現編譯報錯
在開發中引用一個類的規範:
在.h文件中用@class來聲明類,
在.m實現文件中使用#import來包含類的全部內容
#import "Card.h" // @class僅僅是告訴編譯器,Card是一個類 //@class Card;
* #import方式會包含被引用類的全部信息,包括被引用類的變量和方法;@class方式只是告訴編譯器在A.h文件中 B *b 只是類的聲明,具體這個類裏有什麼信息,這裏不須要知道,等實現文件中真正要用到時,纔會真正去查看B類中信息
* 若是有上百個頭文件都#import了同一個文件,或者這些文件依次被#improt,那麼一旦最開始的頭文件稍有改動,後面引用到這個文件的全部類都須要從新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了
* 在.m實現文件中,若是須要引用到被引用類的實體變量或者方法時,還須要使用#import方式引入被引用類
1.autorelease的基本用法 1> 給某個對象發送一條autorelease消息時,會將對象放到一個自動釋放池中 2> 當自動釋放池被銷燬時,會對池子裏面的全部對象作一次release操做 3> 會返回對象自己 4> 調用完autorelease方法後,對象的計數器不變 2.autorelease的好處 1> 不用再關心對象釋放的時間 2> 不用再關心何時調用release 3.autorelease的使用注意 1> 佔用內存較大的對象不要隨便使用autorelease 2> 佔用內存較小的對象使用autorelease,沒有太大影響 4.錯誤寫法 1> alloc以後調用了autorelease,又調用release @autoreleasepool { // 1 Person *p = [[[Person alloc] init] autorelease]; // 0 [p release]; } 2> 連續調用屢次autorelease @autoreleasepool { Person *p = [[[[Person alloc] init] autorelease] autorelease]; } 5.自動釋放池 1> 在iOS程序運行過程當中,會建立無數個池子。這些池子都是以棧結構存在(先進後出) 2> 當一個對象調用autorelease方法時,會將這個對象放到棧頂的釋放池 6.自動釋放池的建立方式 1> iOS 5.0前 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [pool release]; // [pool drain]; 2> iOS 5.0 開始 @autoreleasepool { }
void test() { @autoreleasepool {// { 開始表明建立了釋放池 // autorelease方法會返回對象自己 // 調用完autorelease方法後,對象的計數器不變 // autorelease會將對象放到一個自動釋放池中 // 當自動釋放池被銷燬時,會對池子裏面的全部對象作一次release操做 Person *p = [[[Person alloc] init] autorelease]; p.age = 10; @autoreleasepool { Person *p2 = [[[Person alloc] init] autorelease]; p2.age = 10; } Person *p3 = [[[Person alloc] init] autorelease]; } // } 結束表明銷燬釋放池 }
之前:
Book *book = [[Book alloc] init];
[book release];
如今:
Book *book = [[[Book alloc] init] autorelease]; // 不要再調用[book release];
1.系統自帶的方法裏面沒有包含alloc、new、copy,說明返回的對象都是autorelease的
2.開發中常常會提供一些類方法,快速建立一個已經autorelease過的對象
1> 建立對象時不要直接用類名,通常用self
+ (id)book { return [[[self alloc] init] autorelease]; }
3.外界調用[Book book]時,根本不用考慮在何時釋放返回的Book對象
NSNumber *n = [NSNumber numberWithInt:100]; NSString *s = [NSString stringWithFormat:@"jack"]; NSString *s2 = @"rose";