中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

iOS 內(nèi)存管理

2018-07-20    來(lái)源:編程學(xué)習(xí)網(wǎng)

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

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

iOS 的引用計(jì)數(shù)就類似于下圖中進(jìn)出辦公室的開(kāi)關(guān)燈流程。當(dāng)一個(gè)人A進(jìn)入前,辦公室的引用數(shù)為0,進(jìn)入后需要照明,因此開(kāi)燈,引用數(shù)為1,B進(jìn)入后,引用數(shù)為2,C 進(jìn)入后引用數(shù)為3,以此類推。A 離開(kāi)時(shí),引用數(shù)-1,當(dāng)最后一個(gè)人離開(kāi)辦公室時(shí),引用數(shù)為0,不再需要照明,因此關(guān)燈。


開(kāi)關(guān)燈

對(duì)應(yīng)到 OC 對(duì)象的動(dòng)作時(shí),開(kāi)燈=生成對(duì)象(alloc\new\copy\mutableCopy),需要照明=持有對(duì)象(retain),不需要照明=釋放對(duì)象(release),關(guān)燈=廢棄對(duì)象(dealloc)。


引用計(jì)數(shù)的內(nèi)存管理

1.1 內(nèi)存管理的原則

  • 自己生成的對(duì)象,自己持有
  • 也可持有非自己生成的對(duì)象
  • 釋放不再需要自己持有的對(duì)象
  • 非自己持有的對(duì)象無(wú)法釋放

注意這些原則里的一些關(guān)鍵詞與方法的對(duì)應(yīng)關(guān)系:
『生成』- alloc\new\copy\mutableCopy
『持有』- retain
『釋放』- release
『廢棄』- dealloc

下面分別來(lái)解釋一下,這四條原則的含義:

1.1.1 自己生成的對(duì)象,自己持有

id obj = [[NSObject alloc] init]; id obj = [NSObject new]; id obj = [NSObject copy]; id obj = [NSObject mutableCopy]; // 注意 alloc\new\copy\mutableCopy 開(kāi)頭的駝峰式方法名,也生成并持有對(duì)象 id obj = [MyObject allocMyObj]; id obj = [MyObject newThatObj]; id obj = [MyObject copyThis]; id obj = [MyObject mutableCopyThat];

注意
alloc\new\copy\mutableCopy 開(kāi)頭非駝峰式命名的方法不適用上述規(guī)則。例如:allocate\newer\copying\mutableCopyed。

1.1.2 非自己生成的對(duì)象,也可持有

id obj = [NSMutableArray array];

obj是非『alloc\new\copy\mutableCopy』或以其開(kāi)頭的駝峰式命名方法創(chuàng)建,因此屬于非自己生成的對(duì)象。如何持有對(duì)象呢?用 retain 啊~

id obj = [NSMutableArray array];
[obj retain];

1.1.3 釋放不再需要自己持有的對(duì)象

用alloc\new\copy\mutableCopy』或以其開(kāi)頭的駝峰式命名方法生成并持有的對(duì)象,在不再需要的時(shí)候,要用 release 方法釋放。

id obj = [[NSMutableArray alloc] init]; // do Something... [obj release];
id obj = [NSMutableArray array];
[obj retain]; // do Something... [obj release];

1.1.4 非自己持有的對(duì)象無(wú)法釋放

釋放非自己持有的對(duì)象時(shí),會(huì)發(fā)生崩潰,例如

1)同一個(gè)對(duì)象被多次釋放:

id obj = [[NSMutableArray alloc] init];
[obj release];
[obj release];

2)釋放非自己持有的對(duì)象:

id obj = [obj0 object]; [obj release]; // obj 既不是 alloc\new\copy\mutableCopy 出來(lái)的,也沒(méi)有 retain,因此沒(méi)有被持有,不可以被釋放

2. autorelease

有一個(gè)跟 release 類似的關(guān)鍵詞autorelease,看這樣一段代碼:

- (id)object { id obj = [[NSMutableArray alloc] init];
  [obj autorelease]; return obj;
}

obj 對(duì)象在什么時(shí)候被釋放呢?與 release 的區(qū)別是什么?


release和 autorelease 的區(qū)別


對(duì)象被 release 時(shí),引用計(jì)數(shù)-1,當(dāng)引用計(jì)數(shù)為0時(shí),該對(duì)象被立即釋放。而對(duì)象被 autorelease 時(shí),引用計(jì)數(shù)不變,該對(duì)象被注冊(cè)到自動(dòng)釋放池中,在一個(gè)運(yùn)行周期結(jié)束時(shí),自動(dòng)釋放池被傾倒(池中注冊(cè)的對(duì)象被 release)。

autorelease 類似 C 語(yǔ)言中的局部變量的特性,局部變量超過(guò)其作用域時(shí)會(huì)被自動(dòng)廢棄,autorelease 對(duì)待對(duì)象實(shí)例與之類似。當(dāng)超出 autorelease 的作用域時(shí),對(duì)象實(shí)例的 release 方法被調(diào)用。與 C 語(yǔ)言局部變量不同的是,autorelease 可以設(shè)置其作用域。

for(int i = 0;i  < 10000; i ++){
  @autoreleasepool { // 在一個(gè) runloop 周期內(nèi)產(chǎn)生大量對(duì)象的代碼 }
}

除了上述場(chǎng)景,總結(jié)一下需要顯式調(diào)用 autoreleasepool 的情況:

顯式使用@autoreleasepool:

  • autorelease 機(jī)制基于 UI framework,因此寫(xiě) 非UI framework的程序時(shí),需要自己管理對(duì)象生存周期。

  • autorelease 觸發(fā)時(shí)機(jī)發(fā)生在下一次runloop的時(shí)候。因此如何在一個(gè)大的循環(huán)里不斷創(chuàng)建autorelease對(duì)象,那么這些對(duì)象在下一次runloop回來(lái)之前將沒(méi)有機(jī)會(huì)被釋放,可能會(huì)耗盡內(nèi)存。這種情況下,可以在循環(huán)內(nèi)部顯式使用@autoreleasepool {}將autorelease 對(duì)象釋放。

for (item in BigSet){ @autoreleasepool { //create large mem objects  }
}
  • 自己創(chuàng)建的線程。Cocoa的應(yīng)用都會(huì)維護(hù)自己autoreleasepool。因此,代碼里spawn的線程,需要顯式添加autoreleasepool。

  • 很長(zhǎng)的函數(shù)、很多中間變量時(shí)。
    正常情況下,你創(chuàng)建的變量會(huì)在超出其作用域的時(shí)候被釋放掉。
    而如果函數(shù)寫(xiě)的很長(zhǎng),在函數(shù)運(yùn)行過(guò)程中出現(xiàn)很多中間變量,占據(jù)了大量的內(nèi)存,怎么辦?
    用@autoreleasepool。
    在@autoreleasepool中創(chuàng)建的變量,會(huì)在@autoreleasepool結(jié)束的時(shí)候執(zhí)行一次release,進(jìn)行釋放。其實(shí)@autoreleasepool就相當(dāng)于一層作用域。


3. ARC的規(guī)則

ARC 是從 iOS5出現(xiàn)的編譯器新特性,對(duì)引用采取自動(dòng)計(jì)數(shù),不再需要手動(dòng)的對(duì)對(duì)象進(jìn)行 retain 和 release,編譯器代替我們來(lái)做這件事了。

可以通過(guò)設(shè)置配置文件,在同一個(gè)項(xiàng)目中既有 ARC 也有 MRC(例如受老項(xiàng)目或老第三方庫(kù)影響,需要在 ARC 項(xiàng)目中加入 MRC 的類)。

  • 在 ARC 項(xiàng)目中用到 MRC:在targets的build phases選項(xiàng)下Compile Sources下選擇要不使用arc編譯的文件,雙擊,輸入 -fno-objc-arc ;   
  • 在 MRC 中用到 ARC:同上步驟,選擇要使用arc編譯的文件,雙擊,輸入 -fobjc-arc ;

3.1 所有權(quán)修飾符

ARC 同 MRC 一樣,仍使用引用計(jì)數(shù),仍適用1.1中內(nèi)存管理的4條原則。ARC為何能自動(dòng)釋放呢?關(guān)鍵因素就是—— ARC 中增加了4種所有權(quán)修飾符:

  • __strong
  • __weak
  • __unsafe_unretained
  • __autoreleasing

其中,__strong__weak__autoreleasing對(duì)修飾的局部變量初始化為 nil。

以下著重介紹常用的__strong__weak修飾符.

3.1.1 __strong

__strong 是 id 類型、對(duì)象類型的默認(rèn)所有權(quán)修飾符,在 ARC 有效時(shí)不需要顯式寫(xiě)出,如以下兩行代碼在 ARC 下是相同的:

id obj = [[NSObject alloc] init]; id __strong obj = [[NSObject alloc] init];

__strong 修飾符表示對(duì)對(duì)象強(qiáng)引用,在超過(guò)作用域時(shí)廢棄,釋放所引用的對(duì)象及其成員。相當(dāng)于 MRC 中對(duì)該對(duì)象調(diào)用 release 方法。

__strong在 ARC中是如何實(shí)現(xiàn) MRC的功能的?
對(duì)比 MRC,MRC 通過(guò)手動(dòng)寫(xiě)[obj release]來(lái)釋放自己創(chuàng)建并持有的內(nèi)存;

ARC 通過(guò)增加所有權(quán)修飾符這個(gè)概念,對(duì) id|對(duì)象類型自己創(chuàng)建且持有的對(duì)象默認(rèn)添加__strong 修飾符,從手動(dòng)寫(xiě) release 語(yǔ)句變?yōu)橥ㄟ^(guò)作用域控制對(duì)象及其成員的釋放。

ARC 對(duì)非自己創(chuàng)建但持有的對(duì)象,也通過(guò)默認(rèn)添加 __strong修飾符強(qiáng)引用,使其持有(相當(dāng)于 MRC 中 retain 語(yǔ)句)對(duì)象。

回顧 MRC 內(nèi)存管理的4條原則:

  • 自己生成的對(duì)象,自己持有
  • 也可持有非自己生成的對(duì)象
  • 釋放不再需要自己持有的對(duì)象
  • 非自己持有的對(duì)象無(wú)法釋放

『自己生成的對(duì)象,自己持有』\『也可持有非自己生成的對(duì)象』,ARC 中對(duì) id\對(duì)象類型默認(rèn)添加__strong 修飾符進(jìn)行強(qiáng)引用;『釋放不再需要自己持有的對(duì)象』變量作用域結(jié)束\成員所屬對(duì)象廢棄\對(duì)變量賦值都可以滿足這條;『非自己持有的對(duì)象無(wú)法釋放』ARC 中不再需要寫(xiě) release 語(yǔ)句,因此這條也滿足。因此 ARC 也是完全遵守 MRC 內(nèi)存管理的原則的。

3.1.2 __weak

為解決__strong 導(dǎo)致的循環(huán)引用問(wèn)題,進(jìn)而造成內(nèi)存泄露(廢棄的對(duì)象在超出其生存周期后繼續(xù)存在),需要引入 _weak 修飾符,對(duì)造成循環(huán)引用的對(duì)象進(jìn)行弱引用。當(dāng)作用域結(jié)束時(shí),被強(qiáng)引用的對(duì)象廢棄,弱引用的對(duì)象自動(dòng)被置為 nil。

3.1.3 __unsafe_unretained

iOS4之前用,類似__weak(iOS 5),但需要在使用被其修飾的變量時(shí),先判斷是否存在。

3.1.4 __autorelease

autorelease 修飾符同strong 一樣一般不顯式寫(xiě)出。在 MRC中,通過(guò) NSAutoreleasePool 對(duì)象的聲明和 drain 代碼之間調(diào)用 autorelease 進(jìn)行自動(dòng)釋放。在 ARC中,把需要自動(dòng)釋放的代碼寫(xiě)在@autorelease{// code ...}中,當(dāng)區(qū)間內(nèi)非 alloc\new\copy\mutableCopy\init 的對(duì)象會(huì)被自動(dòng)加入 autoreleasepool,在作用域結(jié)束的時(shí)候釋放。如下圖:


MRC\ARC的自動(dòng)釋放對(duì)比

5. ARC 的規(guī)則

  • 不能顯式使用 retain\release\retainCount\autorelease
  • 不能使用 NSAllocateObject\NSDeallocateObject
  • 要遵守內(nèi)存管理的方法命名規(guī)則(alloc\new\copy\mutableCopy\ init)
  • 不顯式調(diào)用 dealloc
  • 使用@autoreleasepool 替代 NSAutoreleasePool
  • 不使用 NSZone
  • 對(duì)象型變量不能作為 C 語(yǔ)言結(jié)構(gòu)體成員
  • 顯式轉(zhuǎn)換 id 和 void*

來(lái)源:簡(jiǎn)書(shū)

標(biāo)簽: b2c 代碼

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:Lambda表達(dá)式的意義

下一篇:ios 照相機(jī)和相冊(cè)的調(diào)用