每一个东西的产生都是在实际生活迫切需要这样的东西后,人们通过思考发明创造某些东西用以解决这个问题。那么自动释放池用来解决什么问题?请看下面的例子:
对于一些有返回值的消息(方法),它返回的对象要交给谁来释放其内存,比如NSObject类中description消息
-(NSString*)description{ NSString *description; description = [[NSString alloc]initWithFormat:@"hello world"]; return (description); }//description
那么如果让调用者来释放呢,那么就得像下面这样写:
RetainTracker *tracker = [RetainTracker new]; NSString *desc = [tracker description]; [desc release];
苹果公司在Cocoa框架中有一个自动释放池的概念,在NSObject类中提供了一个叫做autorelease的方法。
-(id)autorelease{};//autorelease
-(NSString*)description { NSString *description; description = [[NSString alloc]initWithFormat:@"hello world"]; return ([description autorelease]); }//description
我们上面说了那么多,都在说自动释放池可以帮我们解决掉对象自动释放的问题,但是这个自动释放池也不是自己就存在的,它需要我们自己来显示的创建。可以通过2种方式来创建自动释放池。
当你使用@autoreleasepool{}时,所有在花括号里的代码都会被放入这个池子中。但是任何在该花括号的变量都无法在括号外使用。
该对象需要创建,在该对象创建语句和销毁语句的代码都相当于放入了自动释放池中。
NSAutoreleasePool *pool; pool = [NSAutoreleasePool new]; RetainTracker *tracker = [RetainTracker new]; NSString *desc = [tracker description]; [desc release]; // count: 1 [tracker retain]; // count: 2 NSLog (@"%d", [tracker retainCount]); [tracker retain]; // count: 3 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count: 2 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count: 1 NSLog (@"%d", [tracker retainCount]); [tracker retain]; // count 2 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count 1 NSLog (@"%d", [tracker retainCount]); [tracker release]; // count: 0, dealloc it [pool release];
优先使用@autoreleasepool{}关键字的方式来创建自动释放池。
那么自动释放池的工作原理到底是什么?下面用一个例子来讲解一下。
#import <Foundation/Foundation.h> @interface RetainTracker : NSObject @end // RetainTracker @implementation RetainTracker - (id) init { if (self = [super init]) { NSLog (@"init: Retain count of %d.", [self retainCount]); } return (self); } // init - (void) dealloc { NSLog (@"dealloc called. Bye Bye."); [super dealloc]; } // dealloc @end // RetainTracker int main (int argc, const char * argv[]) { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; RetainTracker *tracker; tracker = [RetainTracker new]; // count: 1 [tracker retain]; // count: 2 [tracker autorelease]; // count: still 2 [tracker release]; // count: 1 NSLog (@"releasing pool"); [pool release]; // gets nuked, sends release to tracker @autoreleasepool { RetainTracker *tracker2; tracker2 = [RetainTracker new]; // count: 1 [tracker2 retain]; // count: 2 [tracker2 autorelease]; // count: still 2 [tracker2 release]; // count: 1 NSLog (@"auto releasing pool"); } return (0); }
2015-02-01 00:12:02.426 09.02 RetainCount-2[860:58571] init: Retain count of 1. 2015-02-01 00:12:02.428 09.02 RetainCount-2[860:58571] releasing pool 2015-02-01 00:12:02.428 09.02 RetainCount-2[860:58571] dealloc called. Bye Bye.
2015-02-01 00:18:23.932 09.02 RetainCount-2[876:61410] init: Retain count of 1. 2015-02-01 00:18:23.933 09.02 RetainCount-2[876:61410] releasing pool 2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] dealloc called. Bye Bye. 2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] init: Retain count of 1. 2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] auto releasing pool 2015-02-01 00:18:23.934 09.02 RetainCount-2[876:61410] dealloc called. Bye Bye. Program ended with exit code: 0