iOS 內(nèi)存管理(一)

內(nèi)存分配

在iOS中,數(shù)據(jù)是存儲(chǔ)在堆和棧上的,堆上的內(nèi)存需要管理,棧上的內(nèi)存并不需要。

  • 非OC對(duì)象(基礎(chǔ)數(shù)據(jù)類(lèi)型)存儲(chǔ)在棧上

??intdouble,float,NSInteger,CGFloatBOOL

  • OC對(duì)象存儲(chǔ)在堆上

?? NSString,NSArrayNSDictionary

引用計(jì)數(shù)

  • MRC引用計(jì)數(shù)

對(duì)象操作的四個(gè)類(lèi)別

對(duì)象操作 OC中對(duì)應(yīng)的方法 對(duì)應(yīng)的 retainCount 變化
生成并持有對(duì)象 alloc/new/copy/mutableCopy等 +1
持有對(duì)象 retain +1
釋放對(duì)象 release -1
廢棄對(duì)象 dealloc -

四個(gè)法則

  • 自己生成的對(duì)象,自己持有。
  • 非自己生成的對(duì)象,自己也能持有。
  • 不在需要自己持有對(duì)象的時(shí)候,釋放。
  • 非自己持有的對(duì)象無(wú)需釋放。

如下是四個(gè)黃金法則對(duì)應(yīng)的代碼示例:

/*
 * 自己生成并持有該對(duì)象
 */
 id obj0 = [[NSObeject alloc] init];
 id obj1 = [NSObeject new];
/*
 * 不在需要自己持有的對(duì)象的時(shí)候,釋放
 */
id obj = [[NSObeject alloc] init]; // 此時(shí)持有對(duì)象
[obj release]; // 釋放對(duì)象
/*
 * 指向?qū)ο蟮闹羔樔跃捅槐A粼趏bj這個(gè)變量中
 * 但對(duì)象已經(jīng)釋放,不可訪問(wèn)
 */
/*
 * 非自己持有的對(duì)象無(wú)法釋放
 */
id obj = [NSArray array]; // 非自己生成的對(duì)象,且該對(duì)象存在,但自己不持有
[obj release]; // 此時(shí)將運(yùn)行時(shí)crash 或編譯器報(bào)error。 非ARC下,調(diào)用該方法會(huì)導(dǎo)致編譯器報(bào) issues。此操作的行為是未定義的,可能會(huì)導(dǎo)致運(yùn)行時(shí) crash 或者其它未知行為

其中 非自己生成的對(duì)象,且該對(duì)象存在,但自己不持有 這個(gè)特性是使用autorelease來(lái)實(shí)現(xiàn)的,示例代碼如下:

- (id) getAObjNotRetain {
    id obj = [[NSObject alloc] init]; // 自己持有對(duì)象
    [obj autorelease]; // 取得的對(duì)象存在,但自己不持有該對(duì)象
    return obj;
}

autorelease 使得對(duì)象在超出生命周期后能正確的被釋放(通過(guò)調(diào)用release方法)。在調(diào)用release 后,對(duì)象會(huì)被立即釋放,而調(diào)用autorelease 后,對(duì)象不會(huì)被立即釋放,而是注冊(cè)到 autoreleasepool 中,經(jīng)過(guò)一段時(shí)間后 pool結(jié)束,此時(shí)調(diào)用release方法,對(duì)象被釋放。

在MRC的內(nèi)存管理模式下,與對(duì)變量的管理相關(guān)的方法有:retain, releaseautorelease。retainrelease 方法操作的是引用記數(shù),當(dāng)引用記數(shù)為零時(shí),便自動(dòng)釋放內(nèi)存。并且可以用 NSAutoreleasePool 對(duì)象,對(duì)加入自動(dòng)釋放池(autorelease 調(diào)用)的變量進(jìn)行管理,當(dāng) drain 時(shí)回收內(nèi)存。

  • ARC引用計(jì)數(shù)

ARC 是蘋(píng)果引入的一種自動(dòng)內(nèi)存管理機(jī)制,會(huì)根據(jù)引用計(jì)數(shù)自動(dòng)監(jiān)視對(duì)象的生存周期,實(shí)現(xiàn)方式是在編譯時(shí)期自動(dòng)在已有代碼中插入合適的內(nèi)存管理代碼以及在 Runtime 做一些優(yōu)化。ARC其實(shí)也是基于引用計(jì)數(shù),只是編譯器在編譯時(shí)期自動(dòng)在已有代碼中插入合適的內(nèi)存管理代碼(包括 retainrelease、copyautorelease、autoreleasepool)以及在 Runtime 做一些優(yōu)化。

現(xiàn)在的iOS開(kāi)發(fā)基本都是基于ARC的,所以開(kāi)發(fā)人員大部分情況都是不需要考慮內(nèi)存管理的,因?yàn)榫幾g器已經(jīng)幫你做了。為什么說(shuō)是大部分呢,因?yàn)榈讓拥?Core Foundation 對(duì)象由于不在 ARC 的管理下,所以需要自己維護(hù)這些對(duì)象的引用計(jì)數(shù)。

還有就算循環(huán)引起情況就算由于互相之間強(qiáng)引用,引用計(jì)數(shù)永遠(yuǎn)不會(huì)減到0,所以需要自己主動(dòng)斷開(kāi)循環(huán)引用,使引用計(jì)數(shù)能夠減少。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容