@autoreleasepool-內存的分配與釋放 開發過iOS、Mac的朋友應該對「 @autoreleasepool 」不陌生。只要在Xcode裏建立一個工程,就能看到下面這樣的代碼: //iOS program int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } //Command line program int main(int argc, const char *argv[]) { @autoreleasepool { //... } return 0; } 看,每一個 main 函數的主體都被 @autoreleasepool 的Block塊包在裏面,也就是說,接下來全部的對象建立都在這個block裏面。 那麼, @autoreleasepool 的做用究竟是什麼呢?咱們開發中能夠用它來作什麼呢? 能夠在某些狀況下,大幅度下降程序的內存佔用,以下圖: 測試的內容:500000次循環,每次循環建立一個NSNumber實例和兩個NSString實例。 圖:紅線表示沒有用 @autoreleasepool 時的內存佔用。 圖:綠線表示用了 @autoreleasepool 優化後的內存佔用! 效果是否是很明顯! 代碼Github地址: AutoReleasePoolTestExample Xcode 6, iOS 8, iPhone 5模擬器. MRC 與 ARC MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),分別對應着手動引用計數和自動引用計數。 對!是計數,不是「 GC、垃圾回收 」什麼的,就是說,在Objective-C的開發中,ARC不表明像Java那樣有GC作垃圾回收,因此本質上仍是要「手動」管理內存的。也就是說,咱們在ARC環境下寫的代碼,不用本身手動插入「 retain、release這些消息 」,ARC會在編譯時爲咱們在合適的位置插入,釋放沒必要要的內存。 而 @autoreleasepool 就跟對象的 release 密切相關。 @autoreleasepool 幹了啥 在MRC時代,若是咱們想先retain一個對象,可是並不知道在何時能夠release它,咱們能夠像下面這麼作: NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString* str = [[[NSString alloc] initWithString:@"tutuge"] autorelease]; //use str... [pool release]; //str is released 就是說,咱們能夠在建立對象的時候給對象發送「 autorelease 」消息,而後當 NSAutoreleasePool 結束的時候,「標記過」autorelease的對象都會被「 release 」掉,也就是會被釋放掉。 可是在ARC時代,咱們不用手動發送 autorelease 消息,ARC會自動幫咱們加。而這個時候, @autoreleasepool 作的事情,跟 NSAutoreleasePool 就如出一轍了。 何時用@autoreleasepool 根據 Apple的文檔 ,使用場景以下: 寫基於命令行的的程序時,就是沒有UI框架,如AppKit等Cocoa框架時。 寫循環,循環裏面包含了大量臨時建立的對象。(本文的例子) 建立了新的線程。(非Cocoa程序建立線程時才須要) 長時間在後臺運行的任務。 利用@autoreleasepool優化循環 利用@autoreleasepool優化循環的內存佔用,我以爲最有用的一點,下面就說說這個點。 以下面的循環,次數很是多,並且循環體裏面的對象都是臨時建立使用的,就能夠用 @autoreleasepool 包起來,讓每次循環結束時,能夠及時的釋放臨時對象的內存。 //來自Apple文檔,見參考 NSArray *urls = <# An array of file URLs #>; for (NSURL *url in urls) { @autoreleasepool { NSError *error; NSString *fileContents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; /* Process the string, creating and autoreleasing more objects. */ } } 這麼作的效果是極其顯著地,就如本文最開始的圖同樣,能夠本身把示例工程下回來運行下試試~ 總結 @autoreleasepool看起來很不「起眼」,日常開發很容易就忽略它了,可是仔細一看,確如此有用~ 參考