autorelease的使用方法如下:
- 生成并持有NSAutoreleasePool对象;
- 调用已分配对象的autorelease实例方法;
- 废弃NSAutoreleasePool对象。
NSAutoreleasePool对象的生命周期相当于c语言变量的作用域。对于所有调用过autorelease实例方法的对象,在废弃NSAutoreleasePool对象是,都自动调用release实例方法。
代码如下:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
id obj = [[NSObject alloc] init];
[obj autorelease];
[pool drain];
上述代码中的最后一行等同于[obj release]。
以GNUstep开源代码为例来看实现原理
static id autorelease_class = nil;
static SEL autorelease_sel;
static IMP autorelease_imp;
/* Set up the autorelease system ... we must do this before using any
* other class whose +initialize might autorelease something.
*/
autorelease_class = [NSAutoreleasePool class];
autorelease_sel = @selector(addObject:);
autorelease_imp = [autorelease_class methodForSelector: autorelease_sel];
/**
* Adds the receiver to the current autorelease pool, so that it will be
* sent a -release message when the pool is destroyed.<br />
* Returns the receiver.<br />
* In GNUstep, the [NSObject+enableDoubleReleaseCheck:] method may be used
* to turn on checking for retain/release errors in this method.
*/
- (id) autorelease
{
if (double_release_check_enabled)
{
NSUInteger release_count;
NSUInteger retain_count = [self retainCount];
release_count = [autorelease_class autoreleaseCountForObject:self];
if (release_count > retain_count)
[NSException
raise: NSGenericException
format: @"Autorelease would release object too many times.\n"
@"%"PRIuPTR" release(s) versus %"PRIuPTR" retain(s)",
release_count, retain_count];
}
(*autorelease_imp)(autorelease_class, autorelease_sel, self);
return self;
}
+ (void) addObject: (id)anObj
{
NSThread *t = GSCurrentThread();
NSAutoreleasePool *pool;
NSAssert(nil != t, @"Creating autorelease pool on nonexistent thread!");
pool = t->_autorelease_vars.current_pool;
if (pool == nil && t->_active == NO)
{
pool = t->_autorelease_vars.current_pool = [self new];
}
if (pool != nil)
{
(*pool->_addImp)(pool, @selector(addObject:), anObj);
}
else
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
if (anObj != nil)
{
NSLog(@"autorelease called without pool for object (%p) "
@"of class %@ in thread %@", anObj,
NSStringFromClass([anObj class]), [NSThread currentThread]);
}
else
{
NSLog(@"autorelease called without pool for nil object.");
}
[arp drain];
}
}
autorelease用一种特殊的方法类实现。这种方法能够高效地运行应用程序中频繁调用的autorelease方法,它被成为“IMP Caching”(可用于iOS app性能优化)。在进行方法调用时,为了解决类名/方法名以及取得的方法运行时的函数指针,要在框架初始化时对其结果值进行缓存。
注:
NSAutoreleasePool * pool = [NSAutoreleasePool alloc] init];
[pool autorelease];
发生crash,通常在使用Foundation框架时,无论调用哪一个对象的autorelease实例方法,实现上是调用的都是NSObject类的autorelease实例方法。但是对于NSAutoreleasePool类,autorelease实例方法已被该类冲载,因此运行时就会出错。