MRC:手動內(nèi)存管理
ARC:默認是ARC:automatic
Reference Count,自動引用計數(shù)器
Person
*p = [[Person alloc] init];
//p就叫做對象的所有者而晒,默認對象出生時,alloc后阅畴,對象引用計數(shù)器值為1
//當(dāng)我們看到new alloc創(chuàng)建對象時倡怎,引用計數(shù)器值為1.
NSLog(@"%lu",p.retainCount);
//retainCount:能夠輸出對象引用計數(shù)器的值
引用計數(shù)器的操作
想要管理對象占用的內(nèi)存,就要學(xué)會操作引用計數(shù)器贱枣。
引用計數(shù)器的常見操作:
retain消息:使計數(shù)器+1(該方法返回對象本身)
release消息:使計數(shù)器-1(不代表釋放對象)
retainCount:獲得對象當(dāng)前的應(yīng)用計數(shù)器值监署,輸出:%ld,%lu
注意:release不代表銷毀對象纽哥,僅僅是引用計數(shù)器-1.
怎么判斷對象被釋放
dealloc方法:只要調(diào)用了這個方法钠乏,就代表對象即將被釋放。
僵尸對象:已經(jīng)被釋放的對象春塌。
野指針:指向僵尸對象的指針晓避。
空指針:指向nil的指針,給空指針發(fā)送消息(調(diào)用方法)不會報任何錯誤只壳。
但是俏拱,如果沒有一個統(tǒng)一的釋放原則,name就會造成代碼的混亂吕世,會都可以釋放彰触,好比一個公司所有的領(lǐng)導(dǎo)沒有分工一樣,任何事命辖,任何一個領(lǐng)導(dǎo)都可以插一嘴况毅。所以,釋放對象要遵循一個原則尔艇,那就是誰創(chuàng)建尔许,誰釋放。
如果在程序結(jié)束后终娃,對象沒有被釋放味廊,此時稱為內(nèi)存泄漏。
釋放對象時棠耕,若要查看釋放情況余佛,重寫dealloc方法:
- (void)dealloc
{
? ? NSLog(@"%d號房間被釋放啦",_fno);
?? ?//這里必須調(diào)用父類的dealloc
? ? [super dealloc];
}
@property參數(shù)
格式:@property(參數(shù)1,參數(shù)2)數(shù)據(jù)類型 方法名
Setter:改set方法的名字
Getter改get方法的名字
什么是內(nèi)存管理:(面試必問)
管理堆區(qū)內(nèi)存的分配和釋放
分配內(nèi)存:newalloc copy
釋放內(nèi)存:release
@class
@class Cat窍荧;//僅僅告訴編譯器Cat是一個貓類辉巡,可以聲明一個對象。
建議:頭文件引入一個類的時候蕊退,使用@class郊楣。
具體使用:
在.h文件中使用@class引用一個類
在.m文件中使用#import包含這個類的.h文件
引入一個類的方法有兩種
#import和@class
區(qū)別:
#import方式會包含被引用類的所有信息,包括被引用類的變量和方法;@class方式只是告訴編譯器在A.h文件中B
? ? ? *b只是類的聲明瓤荔,具體這個類里有什么信息净蚤,這里不需要知道,等實現(xiàn)文件中真正要用到時输硝,才會真正去查看B類中信息今瀑。
使用@class方式由于只需要知道被引用類(B類)的名稱就可以了,而在實現(xiàn)類由于要用到被引用類中的實體變量和方法点把,所以需要使#import來包含被引用類的頭文件橘荠。
通過上面兩點也很容易知道在編譯效率上,如果有上百個頭文件都#import了同一個文件愉粤,或者這些文件一次被#import(A->B,B->C,C->D.砾医。。)衣厘,一旦最開始的頭文件稍有改動如蚜,后面引用到這個文件的所有類都需要重新編譯一遍,這樣的效率也是可想而知的影暴。而相對來講错邦,使用@class方式就不會出現(xiàn)這種問題了;
所以我們實際開發(fā)中盡量在.h頭文件中使用@class
對于循環(huán)依賴關(guān)系來說型宙,比方A類引用B類撬呢,B類也引用A類
這樣嵌套包含的代碼編譯就會報錯
當(dāng)使用@class在兩個類相互聲明,就不會出現(xiàn)編譯器報錯
面試題:#import和@class的區(qū)別妆兑。
作用上的區(qū)別
import會包含引用類的所有信息(內(nèi)容),包括引用類的變量和方法
? ? ? ? @class僅僅是告訴編譯器有這么一個類,具體這個類里有什么信息,完全不知道魂拦。
效率上的區(qū)別
如果有上百個頭文件都#import了同一個文件,或者這些文件依次被#import,那么一旦最開始的頭文件稍有改動,后面引用到這個文件的所有類都需要重新編譯一遍,編譯效率非常低相對來講,使用@class方式就不會出現(xiàn)這種問題了毛仪。
對于循環(huán)retain的情況,對象不能夠釋放芯勘,此時只能讓一方使用assign箱靴。
@property(nonatomic,assign)Girl? ? ? *girl;
NSString
由于字符串是一個特殊的類,因此OC給NSString的retainCount賦值了一個很大的值荷愕,因此開發(fā)的時候不用考慮NSString的內(nèi)存管理問題衡怀。
自動釋放池(ARC)
int main(int argc, const char* argv[]) {
? ? @autoreleasepool {//自動釋放池
? ? ? ? //autorelease:當(dāng)對象調(diào)用這個方法時,就把對象放到了自動釋放池中
? ? ? ? Person *p = [[[Person alloc]init]autorelease];
? ? ? ? //不用關(guān)注對象什么時候被釋放
? ? }//出了花括號,會對池子里面的所有調(diào)用了autorelease方法的對象,做一次release
? ? return 0;
}
ARC特點總結(jié)
不允許調(diào)用release,retain,retainCount
允許重寫dealloc,但是不允許調(diào)用[super dealloc]
@property的參數(shù)
strong:相當(dāng)于原來的retain(適用于OC對象類型)安疗,成員變量是強指針
weak:相當(dāng)于原來的assign(適用于OC對象類型)抛杨,成員變量是弱指針
assign:適用于非OC對象類型(基礎(chǔ)類型)
ARC使用注意事項
ARC中,只要弱指針指向的對象不在了荐类,就直接把弱指針做清空(賦值為nil)操作
_weak Person *p = [[Person alloc]init];//不合理,對象一創(chuàng)建出來就被釋放掉怖现,對象釋放掉后,ARC把指針設(shè)置為nil
ARC在Property處不在使用retain掉冶,而是使用strong真竖,在dealloc中不需要在[super
? ? dealloc],@property(nonatomic,strong)Dog *dog;//意味著生成的成員變量_dog是一個強指針,相當(dāng)于以前的retain厌小。
如果換成是弱指針恢共,則換成weak,不需要加_.