您好,登錄后才能下訂單哦!
Objective-C內(nèi)存管理
管理范疇:OC對(duì)象
每個(gè)計(jì)算機(jī)系統(tǒng)可供程序使用的內(nèi)存資源是有限的。我們要關(guān)心兩件事情:
在需要時(shí)分配,用完之后釋放
不要使用任何已被釋放的內(nèi)存資源,否則將無(wú)用陳舊的值導(dǎo)致各種各樣的錯(cuò)誤發(fā)生
三種管理方式:
手動(dòng)管理方式 MRC(Manual referencing count)
半自動(dòng)管理方式 autoreleasepool
自動(dòng)管理方式 ARC(Auto referencing count)
引用計(jì)數(shù)與內(nèi)存管理準(zhǔn)則
Cocoa采用了一種稱為“引用計(jì)數(shù)”的技術(shù),它為每個(gè)對(duì)象關(guān)聯(lián)一個(gè)整數(shù):
相關(guān)方法:
- (instancetype)retain //引用計(jì)數(shù)+1 - (void)release //引用計(jì)數(shù)-1 - (NSUInteger)retainCount //對(duì)象的當(dāng)前引用計(jì)數(shù)值
使用引用計(jì)數(shù):
a. 當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí)(alloc new copy),被創(chuàng)建對(duì)象的引用計(jì)數(shù)為1
b. 當(dāng)某段代碼要訪問(wèn)這個(gè)對(duì)象時(shí)就對(duì)該引用計(jì)數(shù)+1 (retain)
c. 當(dāng)這段代碼完成后要對(duì)這個(gè)引用計(jì)數(shù)-1 (release)
d. 當(dāng)引用計(jì)數(shù)為0時(shí),表示沒(méi)有代碼訪問(wèn)這個(gè)對(duì)象了,該對(duì)象就會(huì)被銷毀
(銷毀前自動(dòng)向其發(fā)送一個(gè)dealloc消息)。
場(chǎng)景解釋:游戲中的房間、副本等
內(nèi)存管理的準(zhǔn)則:
1)內(nèi)存管理的原則:
只要還有人在使用某個(gè)對(duì)象,那么這個(gè)對(duì)象就不會(huì)被回收;
只要你想使用這個(gè)對(duì)象,那么就應(yīng)該讓這個(gè)對(duì)象的引用計(jì)數(shù)器+1;
當(dāng)你不想使用這個(gè)對(duì)象時(shí),應(yīng)該讓對(duì)象的引用計(jì)數(shù)器-1;
2)誰(shuí)創(chuàng)建,誰(shuí)release
a. 如果你通過(guò)alloc,new,copy來(lái)創(chuàng)建了一個(gè)對(duì)象,那么你就必須調(diào)用release或者autorelease方法
b. 不是你創(chuàng)建的就不用你去負(fù)責(zé)
3)誰(shuí)retain,誰(shuí)release
總結(jié):有始有終,有加有減。
MRC中的代碼規(guī)范
1)只要調(diào)用了alloc,就必須有release
2)屬性的setter方法
a. 基本數(shù)據(jù)類型直接賦值
- (void) setAge:(int) age { _age = age; }
b. OC對(duì)象,先判斷和屬性舊值的是不是同一對(duì)象
如果是,則什么也不做;如果不是,將舊值release,并對(duì)新值retain
- (void) setCar:(Car *) car { if ( car != _car ) { [ _car release]; _car = [ car retain]; } }
3)dealloc方法
a. 對(duì)self所持有的屬性release一次
b. [super dealloc]放在最后
- (void) dealloc { [car release]; [super dealloc]; }
4)不要出現(xiàn)以下垃圾代碼
stu.car = [[Car alloc] init]; //會(huì)使引用計(jì)數(shù)為2 [[Car alloc] init].speed = 100; //無(wú)法釋放了
@property的內(nèi)存管理參數(shù)
@property應(yīng)有且僅有一個(gè)內(nèi)存管理參數(shù)。
MRC下,內(nèi)存管理參數(shù)包括:assign retain copy,默認(rèn)為assign
這些內(nèi)存管理參數(shù),能夠決定屬性setter方法的實(shí)現(xiàn)
assign:setter不修改引用計(jì)數(shù)
@property (nonatomic,assign) NSInteger age;
setter方法:
- (void)setAge:(NSInteger)age { _age = age; }
retain:修改該屬性的引用計(jì)數(shù)(按照代碼規(guī)范)
@property (nonatomic, retain) NSNumber * age;
setter方法:
- (void)setAge:(NSNumber *)age { if ( _age != age ) { [_age release]; _age = [age retain]; } }
copy:深拷貝賦值,一般用于NSString
@property (nonatomic, copy) NSString * name;
setter方法:
- (void)setName:(NSString *)name { if ( _name != nil ) { [_name release]; } _name = [name copy]; }
對(duì)象復(fù)合關(guān)系出現(xiàn)的循環(huán)引用問(wèn)題
問(wèn)題描述:
一個(gè)Person對(duì)象,一個(gè)Card對(duì)象,互為屬性
如果一個(gè)內(nèi)存參數(shù)均為retain,則應(yīng)會(huì)使引用計(jì)數(shù)均為2
這樣做對(duì)任意對(duì)象release,都不會(huì)使對(duì)象銷毀
解決方法:
一端使用retain,一端使用assign
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。