iOS內(nèi)存管理1:引用計(jì)數(shù)
引用計(jì)數(shù):
Objecttive-C使用引用計(jì)數(shù)來進(jìn)行內(nèi)存管理。
然后,引用計(jì)數(shù)其實(shí)是不準(zhǔn)的对粪。
引用計(jì)數(shù)原理:
retain 遞增引用計(jì)數(shù)
release 遞減引用計(jì)數(shù)
autorelease 清理「自動(dòng)釋放池」時(shí),在遞減保留計(jì)數(shù)
關(guān)于過早釋放對(duì)象而導(dǎo)致的bug:
若因某些原因,對(duì)象引用計(jì)數(shù)降至0刑枝,那么對(duì)象所在的內(nèi)存也許會(huì)回收,這樣的話迅腔,其他方法在調(diào)用此對(duì)象可能就使程序崩潰了装畅,這里說是可能,因?yàn)閷?duì)象所占用的內(nèi)存在『解除分配(deallocated)之后沧烈,只是放回「可用內(nèi)存池(avaiable pool)」』如果其他方法調(diào)用此對(duì)象時(shí)掠兄,尚未復(fù)寫對(duì)象內(nèi)存,那么該對(duì)象仍然有效锌雀,這時(shí)程序不會(huì)崩潰蚂夕。 這么說,可能不太好懂腋逆,上代碼:
NSMutableArray *array = [NSMutableArray array];
NSNumber *number = [[NSNumber alloc] initWithInt:1024];
[array addObject:number];
[number release];
NSLog(@"number = %@",number);
這里面我用NSNumber其實(shí)有點(diǎn)不厚道婿牍,但是主要還是讓您記住上面說的。
屬性存取方法中的內(nèi)存管理:
說一下set方法中的先儲(chǔ)存新值惩歉,再釋放舊值和先釋放舊值在儲(chǔ)存新值的區(qū)別:
首先等脂,先儲(chǔ)存新值,再釋放舊值更嚴(yán)謹(jǐn)一些柬泽。
嚴(yán)謹(jǐn)在哪里呢慎菲?
setNumber:(NSNumber *)number{
[number retain];
[number release];
_number = number;
}
先說一下,NSNumber這個(gè)類型很特殊:
NSNumber *number1 = [[...alloc]int:11];
NSNumber *number2 = [[...alloc]int:11];
這個(gè)number1和number2的內(nèi)存地址是相同的锨并。
關(guān)于NSNumber的問題露该,如果想了解的話,可以看看第煮,唐巧前輩寫的這兩篇文章:
http://www.devtang.com/blog/2014/05/30/understand-tagged-pointer/
http://blog.xcodev.com/archives/tagged-pointer-and-64-bit/
經(jīng)jocker提醒解幼,setter方法建議這么寫
- (void)setBlackBoard:(Blackboard *)blackBoard
{
if (_blackBoard != blackBoard) {
[_blackBoard release];
_blackBoard = [blackBoard retain];
}
}
跑偏了抑党,我們往回說:
如果,新舊兩值指向同一個(gè)對(duì)象撵摆,那么若先執(zhí)行釋放底靠,就可能導(dǎo)致系統(tǒng)將此對(duì)象永久回收,而后續(xù)的保留操作對(duì)已經(jīng)回收的對(duì)象是無用的特铝,這個(gè)實(shí)例變量就變成了懸掛指針暑中。
自動(dòng)釋放池:
自動(dòng)釋放池和release的區(qū)別:
release會(huì)立刻遞減對(duì)象的保留計(jì)數(shù),可能令系統(tǒng)立即回收它鲫剿,注意是可能鳄逾。
自動(dòng)釋放池呢,假如自動(dòng)釋放池的對(duì)象灵莲,會(huì)稍后遞減雕凹,這個(gè)稍后一般指下一次event loop
的時(shí)候,注意這里是一般,不是說絕對(duì)政冻。
自動(dòng)釋放池多用于跨方法調(diào)用枚抵,書上的原話說,自動(dòng)釋放池可以保證對(duì)象在跨越「方法調(diào)用邊界」(method call boundary)后一定存活明场,實(shí)際上汽摹,釋放操作會(huì)在清空最外層的自動(dòng)釋放池時(shí)執(zhí)行,除非你有自己的自動(dòng)釋放池榕堰,否則這個(gè)時(shí)機(jī)指的就是當(dāng)前線程的下一次事件循環(huán)竖慧。
循環(huán)引用
A對(duì)象中一個(gè)屬性是B的實(shí)例嫌套,B對(duì)象中一個(gè)屬性是C的實(shí)例逆屡,C對(duì)象中一個(gè)屬性是A的實(shí)例。這就構(gòu)成了循環(huán)引用踱讨。
當(dāng)然魏蔗,這么說是不嚴(yán)謹(jǐn)?shù)模囊桓模?br>
A強(qiáng)引用了b痹筛,B強(qiáng)引用了c莺治,C強(qiáng)引用了a,這就構(gòu)成了循環(huán)引用帚稠。
解決的兩個(gè)方法:
1谣旁、改強(qiáng)引用為弱引用。
2滋早、從外屆命令循環(huán)中的某個(gè)對(duì)象榄审,不在引用另外一個(gè)對(duì)象。
釋放的時(shí)機(jī):
本文多次說了杆麸,可能會(huì)回收內(nèi)存搁进,可能會(huì)回收內(nèi)存浪感,內(nèi)存究竟在什么時(shí)候回收呢:
幾句話:
1.釋放操作是RunLoop管理的 要RunLoop運(yùn)行到釋放的時(shí)候才會(huì)被釋放,RunLoopEnterwaiting的時(shí)候就釋放了
2.釋放是統(tǒng)一處理的 不是某個(gè)對(duì)象為引用計(jì)數(shù)為0就把他立即釋放了饼问。
3.CoreFoundation對(duì)象和OC對(duì)象互轉(zhuǎn)的釋放問題 CF對(duì)象是不支持ARC的 要自己管理
參考:
Effective Objective-2.0 29Tip
感謝:
五角星群:絕影影兽,jocker,及其他群友莱革。
define_Coder群:張海龍峻堰,Archer,iOS小熊盅视,Calf等其他群友茧妒。