標籤:style blog http io ar color os 使用 sp
本篇博文,將給大家介紹下再Objective-C中如何使用記憶體管理。一個程式啟動並執行時候,如果不及時的釋放沒有用的空間記憶體。那麼,程式會越來越臃腫,記憶體佔用量會不斷升高。我們在使用的時候,就會感覺很卡,最終使得程式運行奔潰。因此,將無效的記憶體及時清理釋放,是非常有必要的。
一個對象在最初建立使用,到最後的回收釋放,經曆的是怎樣一個過程呢?
包括:誕生(通過alloc或new方法實現)、生存(接收訊息並執行操作)、交友(通過複合以及向方法傳遞參數)、最終死去(被釋放掉)。
一、引用計數
在對象建立的時候,Cocoa使用了一種叫引用計數的技術:
1)當一個對象被訪問的時候,引用計數器的值就加1,可以給對象發送一條retain訊息;
2)當結束該對象的訪問的時候,引用計數器的值就減1,可以給對象發送一條release訊息;
3)當引用計數器的值為0的時候,表示不再訪問該對象,則其佔用的系統記憶體將被回收重用,會自動給對象發送一條dealloc訊息,一般都會重寫dealloc方法;
4)要獲得保留計數器當前的值,可以發送retainCount訊息。
下面,介紹下幾種方法的聲明和實現方法:
首先,建立一個RetainTracker的類,修改類的聲明檔案和實現方法:
1 // RetainTracker.h2 3 #import <Foundation/Foundation.h>4 5 @interface RetainTracker : NSObject6 -(id) retain;7 -(oneway void)release;8 -(NSUInteger)retainCount;9 @end
1 // RetainTracker.m 2 3 #import "RetainTracker.h" 4 5 @implementation RetainTracker 6 -(id) init 7 { 8 if(self == [super init]) 9 {10 NSLog(@"init: Retain count of %lu.", [self retainCount]);11 }12 return (self);13 }14 15 -(void) dealloc16 {17 NSLog(@"dealloc called. ByeBye!");18 [super dealloc];19 }20 21 @end
然後在main.m主函數中調用retain,release,retainCount,dealloc等方法:
1 #import <Foundation/Foundation.h> 2 #import "RetainTracker.h" 3 4 int main(int argc, const char * argv[]) 5 { 6 RetainTracker *tracker = [RetainTracker new];// count =1 7 8 [tracker retain]; 9 NSLog(@"retainCount: %lu", [tracker retainCount]);// count =210 11 [tracker retain];12 NSLog(@"retainCount: %lu", [tracker retainCount]);// count =313 14 [tracker release];15 NSLog(@"retainCount: %lu", [tracker retainCount]);// count =216 17 [tracker release];18 NSLog(@"retainCount: %lu", [tracker retainCount]);// count =119 20 [tracker retain];21 NSLog(@"retainCount: %lu", [tracker retainCount]);// count =222 23 [tracker release];24 NSLog(@"retainCount: %lu", [tracker retainCount]);// count =125 26 [tracker release];// count =0, dealloc27 28 return (0);29 }
運行結果如下:
二、自動釋放
大家都知道,當對象不再使用的時候,要及時釋放。但是在某些情況下,弄清楚什麼時候不再使用一個對象並不容易。如果能夠自動釋放就好了。很幸運,Cocoa中有一個自動釋放池(autorelease pool)。細心的朋友可以發現,在ios5以後,每次建立項目,在main函數中都有個@autoreleasepool方法,這就是將執行的代碼都加到自動釋放池中。
NSObject類提供了一個叫做autorelease的方法:
1 -(id) autorelease;
該方法預先設定一條會在未來某個時間發送的release訊息。當給一個對象發送autorelease訊息的時候,實際上是將該對象添加到自動釋放池中。當自動釋放池被銷毀時,會向該池中的所有對象都發送release訊息。
那麼,接下來,我們就用添加到自動釋放池的方法來修改上面的例子。RetainCount類的內容不改變,只要修改main主函數中的內容:
1 /* use auto release pool */ 2 int main(int argc, const char * argv[]) 3 { 4 NSAutoreleasePool *pool; 5 pool = [[NSAutoreleasePool alloc] init]; 6 7 RetainTracker *tracker = [RetainTracker new];// count =1 8 NSLog(@"after new, tracker: %lu", [tracker retainCount]);// count =1 9 10 [tracker retain];11 NSLog(@"after retain, tracker: %lu", [tracker retainCount]);// count =212 [tracker autorelease];13 NSLog(@"after autorelease, tracker: %lu", [tracker retainCount]);// count =214 15 [tracker release];16 NSLog(@"after release, tracker: %lu", [tracker retainCount]);// count =117 NSLog(@"releasing pool");18 [pool release]; // 銷毀自動釋放池19 20 @autoreleasepool {21 RetainTracker *tracker2;22 tracker2 = [RetainTracker new]; // count = 123 [tracker2 retain]; //count =224 [tracker2 autorelease]; // count still = 225 [tracker2 release]; //count = 126 NSLog(@"auto releasing pool.");27 }28 29 return (0);30 }
運行結果:
tracker對象,通過autorelease訊息,將該對象添加到自動釋放池中。當pool自動釋放池發送release訊息的時候,pool對象的引用計數器的值為0,則該自動釋放池要被銷毀,其dealloc方法被調用。使得自動釋放池中的對象也都跟隨其一起被銷毀。
在下篇博文中,我們將繼續介紹OC中記憶體管理的相關知識,介紹Cocoa的記憶體管理規則。
《objective-c基礎教程》學習筆記(十)—— 記憶體管理之對象生命週期