NSAutoreleasePool类

本文深入探讨了自动释放池在Cocoa框架中的作用,如何在引用计数环境中支持内存管理,以及如何在不同场景下有效使用自动释放池避免内存泄露。详细解释了自动释放池的工作原理、方法及其在Cocoa应用开发中的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承自NSObject
符合NSObject(NSObject)
框架/System/Library/Frameworks/Foundation.framework
可用性可用于iOS 2.0或者更晚的版本
声明于NSAutoreleasePool.h
参考指南Advanced Memory Management Programming Guide
示例代码

CoreTextPageViewer

ListAdder

ScrollViewSuite

TableViewSuite

TopSongs

概览

NSAutoreleasePool被用于支持Cocoa的内存管理系统的引用计数。

重要:如果使用了自动引用计数(ARC),你便不能直接使用自动释放池。作为替代,你可以使用@autoreleasepool语法块。例如,在使用自动释放池的地方:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//code
[pool release];
你应该这么写:
@autoreleasepool{
//code
}
@autoreleasepool语法块比直接使用NSAutoreleasePool实例更加高效,你甚至可以在不使用ARC的时候使用它们。

在引用计数环境中(相对于使用垃圾回收),NSAutoreleasePool对象包含一些收到自动释放消息的对象,这些对象在自动释放池倒掉的时候会释放掉。因此,使用autorelease代替release可以扩大一个对象的存在时间,至少可以扩大到这个自动释放池被倒掉(如果这个对象被retain过,它的寿命会更长)。一个对象可以被投入相同的池若干次,在这种情况下,它每次都会收到一个释放消息。
在引用计数环境中,Cocoa期望存在一个始终可用的自动释放池。如果一个池是不可用的,自动释放的对象将不会得到释放,从而会导致内存泄露。在这个情况下,你的程序会报出适当地警告信息。

应用程序套件在main线程中的每个时间循环开始的时候会创建一个自动释放池,然后在结束的时候倒掉,从而释放掉当处理一个事件产生的任何对象。如果你使用这个应用程序套件,你因此通常不需要自己创建的自动释放池。然而如果你的应用程序在事件循环中创建了大量临时的自动释放对象,创建一个自动释放池将有利于缩小内存占用的峰值。

你使用alloc和init创建一个NSAutoreleasePool对象,然后使用drain或者release来处理它,要理解这两者的区别,参考123页的Garbage Collection。自动释放池无法被持有,倒掉一个自动释放池最终会有一个销毁的效果。你应该在创建一个释放池同样地上下文中(方法或者函数的调用,或者一个循环体中)倒掉他。

每个线程(包括主线程)维护它自己的自动释放池对象的栈。当创建一个新的池的时候,它被添加到栈顶。当池被销毁的时候,它们从栈中移除。在当前线程中,自动释放对象被放进最顶部的自动释放池。当一个线程结束时,它自动倒掉所有与自己相关的自动释放池。

线程

如果你在制作一个在应用程序套件之外调用的Cocoa,例如你创建一个基础的应用程序或者分离一个线程,这时候你就需要创建你自己的自动释放池。

如果你的应用程序或者线程是长寿命的,并且会潜在的生成大量的自动释放的对象,你需要定期的倒掉和创建自动释放池(就像是Cocoa在主线程中做的那样),否则,随着自动释放对象的积累,你的内存峰值会一直增长。然而,如果你仅仅是分离线程而不产生Cocoa调用,你就不需要创建自动释放池。

注:如果你使用POSIX线程APIs创建次要的线程而不是使用NSThread对象,你将无法使用Cocoa,包括NSAutoreleasePool,除非Cocoa在多线程模块。Cocoa进入多线程模块仅仅在分离出它的第一个NSThread对象之后。要像在次要的POSIX线程中使用Cocoa,你的应用程序必须至少分离一个可以立即退出的NSThread对象。你可以使用NSThread类方法isMultiThreaded来测试Cocoa是否在多线程模块。

垃圾回收

在垃圾回收环境中是不需要自动释放池的。然而,你可以写一个框架设计成可以同时在垃圾回收和引用计数环境中使用。在这种情况下,你可以使用自动释放池来暗示垃圾在适当的时候回收。在垃圾回收环境中,如果有必要可以给自动释放池发送一个drain消息来触发垃圾回收,然而release是一个空操作。在引用计数环境中,drain与release拥有相同的效果。因此通常情况下,你应该使用drain来代替release。

类方法

+ addObject:

将给出的对象添加到当前线程中活跃的自动释放池中。

+ (void)addObject:(id)object

参数object:加到释放池中的对象
返回值 

论述

同一个对象可以被多次加到一个活跃的释放池中,当释放池被销毁时,池中的所有对象都会收到一个release消息。

通常不需要直接调用这个方法,你可以通过向对象发送一个autorelease消息来代替。

实例方法

- addObject:

将给出的对象添加到接收者中。

- (void)addObject:(id)object

参数objcet:加到接收者中的对象
返回值 

论述

同一个对象可以被多次加到一个活跃的释放池中,当释放池被销毁时,池中的所有对象都会收到一个release消息。

通常不需要直接调用这个方法,你可以通过向对象发送一个autorelease消息来代替。

- autorelease

引发一个异常。

返回值

self。

论述

在引用计数环境中,该方法引发一个异常。

- drain

在引用计数环境中,释放以及弹出接收者;在垃圾回收环境中,如果自最近一个回收起,垃圾已经超过当前的门槛,将会触发垃圾回收。

- (void)drain

论述

在引用计数环境中,该方法与release的效果相同。自动释放池无法被持有,因此这将会导致接收者被销毁。当自动释放池被销毁时,向池中所有的自动释放对象发送release消息。如果一个对象多次被添加到同一个自动释放池中,当池被销毁时,它每一次的添加都会收到一个release消息。

特别注意事项

在垃圾回收环境中,release是空操作,因此除非你不想给回收者一个暗示,它对于在任何可以编译到垃圾回收环境中的代码中使用drain是非常重要的。

- release

释放并且弹出接收者。

- (void)release

论述

在引用计数环境中,自动释放池无法被持有,这个方法会导致接收者被销毁。当自动释放池被销毁时,它会向池中所有的自动释放对象发送release消息。如果一个对象多次被添加到同一个自动释放池中,当池被销毁时,它每一次的添加都会收到一个release消息。

在垃圾回收环境中,这个方法是一个空操作。

特别注意事项

你应该通常使用drain来代替release。

- retain

引发一个异常。

返回值。

self。

论述

在引用计数环境中,这个方法会引发一个异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值