導(dǎo)語:
Objective-C 和 Swift 語言的內(nèi)存管理方式都是基于引用計數(shù)的腹备,引用計數(shù)是一個簡單而有效的管理對象生命周期的方式谭贪。引用計數(shù)分為手動引用計數(shù)ARC:和自動引用計數(shù)MRC,現(xiàn)在開發(fā)基本上都會選擇ARC令花。下面簡單介紹下內(nèi)存管理的一些知識阻桅。
1.為什么要進行內(nèi)存管理?
1.應(yīng)用程序的內(nèi)存管理是一個在程序運行時進行內(nèi)存分配兼都,程序結(jié)束時釋放內(nèi)存的過程嫂沉,書寫良好的程序,會盡可能少占用內(nèi)存扮碧。
2.移動設(shè)備的內(nèi)存是有限的趟章,每個程序都會分配一定的內(nèi)存,如果程序超出內(nèi)存限額慎王,程序?qū)罎ⅰ?br>
3.我們必須確保在需要的時候分配內(nèi)存蚓土,在不使用的時候回收內(nèi)存。
2.內(nèi)存管理概述
1.在OC中赖淤,所有的對象都在堆區(qū)分配空間蜀漆,OC采用引用計數(shù)的方法管理對象的生命周期,由程序猿負責(zé)釋放對象所占用的內(nèi)存咱旱。
2.OC里有3種內(nèi)存管理機制:
3.對象的所有權(quán)
OC的內(nèi)存管理模型嗜愈,是基于對象的“所有權(quán)”。
所有權(quán)的管理規(guī)則:
(1)當(dāng)你使用alloc莽龟,new,copy锨天,mutableCopy等方法創(chuàng)建對象毯盈,你擁有對象的所有權(quán);
(2)你可以用retain來實現(xiàn)對一個對象的所有病袄;
(3)你不再需要一個對象時搂赋,你必須放棄對對象的持有(release)赘阀;
4.引用計數(shù)
所有權(quán)策略是通過引用計數(shù)來實現(xiàn)的,通常稱之為“retain count”脑奠,每個對象都有一個“retain count”;
(1)當(dāng)創(chuàng)建(alloc, new, copy, mutablecopy)一個對象時基公,它的引用計數(shù)為1;
(2)發(fā)送retain消息給一個對象時宋欺,它的引用計數(shù)加1轰豆;
(3)發(fā)送release消息給一個對象時,它的引用計數(shù)減1齿诞;
(4)autorelease:如果對象不能立刻釋放酸休,可以向?qū)ο蟀l(fā)送autorelease消息,使對象的引用計數(shù)在未來的某個時候減1祷杈,并且在那個時候放棄對象的所有權(quán)斑司;
(5)如果對象的引用計數(shù)是0,系統(tǒng)會向?qū)ο蟀l(fā)送dealloc消息但汞,然后釋放對象的內(nèi)存宿刮;
5.內(nèi)存管理相關(guān)方法
(1)對象引用計數(shù)加1,返回對象本身
- (id)retain;
(2)對象引用計數(shù)減1
- (id)release;
(3)不改變引用計數(shù)私蕾,返回對象當(dāng)前的引用計數(shù)的值
- (unsigned)retainCount;
(4)這個方法在對象引用計數(shù)為0的情況下僵缺,當(dāng)內(nèi)存回收的時候系統(tǒng)自動調(diào)用
- (void)dealloc;
6.自動釋放池
自動釋放池(Autorelease pool)的機制,為你提供了一個“延時”釋放對象的機制是目。當(dāng)你既想放棄對象所有權(quán)谤饭,又不想發(fā)生立即放棄行為,這時候懊纳,你可以向?qū)ο蟀l(fā)送一個autorelease消息揉抵,將對象加入到自動釋放池。
(1)自動釋放池的寫法
4.3以后
@aytoreleasepool{
}
4.3以前
NSAutoreleasePool *pool =[ [NSAutoreleasePool alloc]init];
……
[pool drain];
(2)當(dāng)你向?qū)ο蟀l(fā)送autorelease消息時嗤疯,你已經(jīng)失去了對象的所有權(quán)冤今,所以你不用負責(zé)釋放對象;
(3)自動釋放池獲得了對象的所有權(quán)茂缚,當(dāng)池子釋放時戏罢,會自動向池子里的每一個對象發(fā)送release消息
7.引用計數(shù)和存取器
***setter正確寫法***
正確寫法1
- (void)setName:(NSString *)aName
{
[aName retain];
[name release];
name = aName;
}
正確寫法2
- (void)setName:(NSString *)aName
{
if(name != aName) {
[name release];
name = [aName retain];
}
正確寫法3 不推薦
- (void)setName:(NSString *)aName
{
[aName autorelease];
name = aName;
}
8.引用計數(shù)和字符串
(1)NSString字符串的內(nèi)存管理和普通對象不同;
(2)常量符串在文字常量區(qū)脚囊,沒有引用計數(shù)龟糕;
(3)NNString方法在創(chuàng)建的對象不一定有引用計數(shù),關(guān)鍵卡對象是否在堆區(qū)分配內(nèi)存悔耘;
(4)NSMutableString產(chǎn)生的對象都在堆區(qū)讲岁,都有引用計數(shù)于樟;
9.引用計數(shù)和集合
(1)如果一個對象被放到了集合(Array吗冤,Dictionary攒庵, Set)中芳撒,集合會取得對該對象的所有權(quán),對象的引用計數(shù)會加1阶淘;
(2)從集合刪除對象時衙吩,對象引用計數(shù)減1;
(3)當(dāng)集合自己release的時候溪窒,集合會放棄對該對象的所有權(quán),集合里的所,有對象引用計數(shù)減1霉猛;
10.自動引用計數(shù)---ARC(Automatic Reference Counting)
Xcode 4.2之后引入了自動引用計數(shù)尺锚,ARC是一個編譯期的計數(shù),ARC在編譯期為每個對象添加合適的retain, release惜浅。
ARC規(guī)則
1.禁止任何形式的調(diào)用和實現(xiàn):dealloc瘫辩,retain,release坛悉,retainCount伐厌,autorelease。dealloc可以實現(xiàn)但禁止調(diào)用[super dealloc];
2.不可以使用NSAllocateObject或者NSDeallocateObject裸影,使用alloc申請一塊內(nèi)存后挣轨,其他的都可以交給運行期的自動管理;
3.不能在C語言中的結(jié)構(gòu)體使用OC中的類的指針轩猩;
4.不能使用NSAutoreleasePool卷扮,作為替代,@autoreleasepool被引入均践;
5.禁止以new開頭的屬性變量命名晤锹。
1. 創(chuàng)建完工程后,決定是否使用ARC
2. 對工程里的單個文件不使用ARC:在targets的build phases選項下compile Sources下選擇不使用ARC編譯的文件彤委,雙擊它鞭铆,輸入-fno-objc-arc。
3. 強引用和弱引用使用ARC后焦影,OC中的對象指針车遂,可以分為強引用(strong reference)和弱引用(weak reference)
<1>強引用指針?biāo)赶虻膶ο螅瑫詣颖3衷搶ο髍etain;
<2>弱引用指針?biāo)笇ο笏钩剑粫詣颖3衷搶ο蟛暗#绻笇ο筢尫牛撝羔樧詣又脼閚il彬呻;
<3>如果一個對象沒有任何強引用指針指向衣陶,會自動釋放回梧;
<4>默認指針是強引用的
4.ARC下屬性設(shè)置
weak:delegate和outlet使用;
assign:一般值類型變量用該屬性聲明祖搓,比如:int, bool湖苞,或者省略不寫
retain:該屬性與strong一致拯欧,用于對象,只是可讀性更強一些
strong:用于對象
copy:一般用于字符串
只讀屬性:
下面的變量聲明在ARC將會出錯
@property (nonatomic, readonly)NSString *name;
應(yīng)該寫為
@property (nonatomic, strong, readonly)NSString *name;