iOS的內(nèi)存管理有兩種方式:1.手動(dòng)管理(手動(dòng)引用計(jì)數(shù),Manual Reference Counting);2.自動(dòng)引用計(jì)數(shù)(Automatic Reference Counting)。
先說一下引用計(jì)數(shù)(Reference Counting):這里打個(gè)比方吧,假如某個(gè)籠子里有一個(gè)機(jī)械式的微型舞臺(tái)劇,當(dāng)有人出現(xiàn)在這個(gè)籠子面前,并按了一個(gè)按鈕(alloc/init)啟動(dòng)機(jī)械開始表演舞臺(tái)劇時(shí),舞臺(tái)劇就開始了。一旦有新的觀眾來看這個(gè)舞臺(tái)劇,觀眾數(shù)就會(huì)加一,只要觀眾數(shù)不為零,這個(gè)舞臺(tái)劇就會(huì)一直演下去,但是一旦觀眾數(shù)為零,那這個(gè)舞臺(tái)劇就會(huì)被自動(dòng)結(jié)束掉,如果有人想看,就只能等人再次按(alloc/init)按鈕了。
1.手動(dòng)管理(手動(dòng)引用計(jì)數(shù)):
雖說和C/C++一樣,程序員都是手動(dòng)進(jìn)行管理,但是ObjectiveC的這種內(nèi)存管理方式和C/C++是不太一樣的,一是OC在內(nèi)存釋放時(shí),程序員操作的是內(nèi)存引用計(jì)數(shù),而不是直接對(duì)內(nèi)存進(jìn)行free操作;二是ObjectiveC比C/C++多一個(gè)NSAutoreleasePool(推薦使用的是@autoreleasepool,這個(gè)在ARC模式下也是可以使用的,書上說這個(gè)比NSAutoreleasePool性能和效率都更好,但是沒有說為什么,喜歡追根究底的同學(xué)自行測(cè)試一下或者查找相關(guān)的文檔吧),自動(dòng)釋放池,當(dāng)我們遇到很多只用一次就不再使用的對(duì)象時(shí),就可以使用實(shí)例對(duì)象,用法如下:
/******** NSAutoreleasePool ********/
id ?pool = [[NSAutoreleasePool alloc] init];
/* 在這個(gè)地方可以 alloc 我們需要的只需要用一次的對(duì)象實(shí)例,初始化之后直接調(diào)用autorelease,比如:Obj *obj = [[[Obj alloc] init] autorelease];*/
[pool release];
/******** @autoreleasepool ********/
@autoreleasepool {
/* 在這個(gè)地方可以 alloc 我們需要的只需要用一次的對(duì)象實(shí)例,初始化之后直接調(diào)用autorelease,比如:Obj *obj = [[[Obj alloc] init] autorelease];*/
}
需要注意的地方是,autorealse作為NSObject類的方法,只能和NSAutoreleasePool一起使用,如果不存在自動(dòng)釋放池的實(shí)力對(duì)象的情況下使用autorelease會(huì)出現(xiàn)運(yùn)行時(shí)錯(cuò)誤。另外,在循環(huán)體while/for等等內(nèi)使用自動(dòng)釋放池,在break和continue之前注意release自動(dòng)釋放池;還有就是自動(dòng)釋放池中,實(shí)例對(duì)象的retain和autorelease注意成對(duì)使用。
2.自動(dòng)引用計(jì)數(shù)(ARC):
自動(dòng)引用計(jì)數(shù)其實(shí)是目前大家都愿意使用、也是最推薦使用的內(nèi)存方式。
這種方式是基于引用計(jì)數(shù)的一種編譯期技術(shù),其原理就是在編譯過程中,在源代碼合適的地方添加retain、release、autorelease等函數(shù)調(diào)用,這樣我們就不需要自己手動(dòng)去調(diào)用release或者autorelease了,既不容易出現(xiàn)混亂,也可以少寫一些重復(fù)性的代碼,在這種情況下就不允許手動(dòng)調(diào)用這些對(duì)引用計(jì)數(shù)操作的函數(shù)了(retain、release、autorelease、retainCount).另外,ARC模式下,也不允許使用memset、memcpy、bzero等直接對(duì)內(nèi)存進(jìn)行操作的函數(shù),這個(gè)其實(shí)是為了防止內(nèi)存段錯(cuò)誤。
需要注意的地方除了上面說到的一些,另外就是弱引用和強(qiáng)引用,因?yàn)檫@個(gè)問題過于普通,這里就不說了,盡量確定項(xiàng)目中各個(gè)實(shí)例對(duì)象的強(qiáng)引用是一個(gè)樹形結(jié)構(gòu),不要出現(xiàn)循環(huán)就好了。對(duì)于關(guān)鍵字__strong和__weak,strong說明是強(qiáng)引用,weak還具有自動(dòng)nil化作用,即當(dāng)weak指針指向的對(duì)象實(shí)例被釋放了,該指針會(huì)自動(dòng)被置為nil,有點(diǎn)類似于C++里面的引用,不過這個(gè)是指針的引用(C++里面只有類的引用,卻沒有指針的引用,C++里的指針和引用還是不一樣的,所以指針的指針不算是引用,具體請(qǐng)查閱《C++ premier》),其實(shí)還有一個(gè)__unsafe_unretained,這個(gè)就是不能自動(dòng)nil化的弱引用(__weak),如果沒有必要不要用,可能會(huì)出現(xiàn)野指針。
那么這里回到最前面說的舞臺(tái)劇那兒,關(guān)于觀眾的問題。strong指針表示一個(gè)直接觀看舞臺(tái)劇的觀眾,weak指針表示背對(duì)舞臺(tái)劇不愿意看舞臺(tái)劇,卻又關(guān)注舞臺(tái)劇發(fā)展的觀眾,這種觀眾并不被記入有效觀眾的數(shù),所以不要讓這種觀眾去按動(dòng)開始舞臺(tái)劇按鈕(alloc/init),因?yàn)檫@種觀眾不作數(shù),出來就直接讓舞臺(tái)劇結(jié)束了(現(xiàn)在的編譯器會(huì)對(duì)這種情況出現(xiàn)告警,個(gè)人覺得,在不必要的情況下,不要出現(xiàn)任何告警是最好的)。
其實(shí),Mac OS下還有一種內(nèi)存管理方式,就是(垃圾回收)機(jī)制,這種方式并不能在IOS下使用。簡(jiǎn)單的記一下吧,就是在程序運(yùn)行過程中,當(dāng)內(nèi)存使用的情況達(dá)到一定數(shù)量時(shí),就會(huì)檢查內(nèi)存空間看有沒有不再使用的內(nèi)存,有的話就直接回收掉。用戶也可以手動(dòng)調(diào)用函數(shù),去檢查內(nèi)存空間狀態(tài)下是否有可釋放的內(nèi)存。
就這些吧。。。。。。。