Autorelease pool blocks provide a mechanism whereby you can relinquish ownership of an object, but avoid the possibility of it being deallocated immediately (such as when you return an object from a method). Typically, you don’t need to create your own autorelease pool blocks, but there are some situations in which either you must or it is beneficial to do so.
自动释放池提供了一种机制,你可以放弃一个对象的所有权,但是又避免了立即释放对象,例如当你要从一个方法返回一个对象的时候。通常你不需要创建你自己的自动释放池。但是,有几种情况你必须创建或者创建后是有好处的。
About Autorelease Pool Blocks
关于自动释放池
An autorelease pool block is marked using@autoreleasepool, as illustrated in the following example:
自动释放池用@autoreleasepool,标识,像下边这样。
@autoreleasepool {
// Code that creates autoreleased objects.
}
At the end of the autorelease pool block, objects that received an autorelease message within the block are sent a release message—an object receives a release message for each time it was sent an autorelease message within the block.
在自动释放池的末尾,在block内部,那些收到autorelease消息的对象会被发送一条autorelease消息。在block内,每次那个收到autorelease消息的对象,也会收到release消息。
Like any other code block, autorelease pool blocks can be nested:
一些其他情况,自动释放池会进行嵌套。
@autoreleasepool {
// . . .
@autoreleasepool {
// . . .
}
. . .
}
(You wouldn’t normally see code exactly as above; typically code within an autorelease pool block in one source file would invoke code in another source file that is contained within another autorelease pool block.) For a given autorelease message, the corresponding release message is sent at the end of the autorelease pool block in which the autorelease message was sent.
(正常情况下,你不会显示的看到上边的代码,一般,在一个源文件的自动释放池会调用在另外一个含有自动释放池的源文件中调用)。对于一条给定的autorelease消息,相应的release消息会在发送autorelease消息的自动释放池的末尾进行发送。
Cocoa always expects code to be executed within an autorelease pool block, otherwise autoreleased objects do not get released and your application leaks memory. (If you send an autorelease message outside of an autorelease pool block, Cocoa logs a suitable error message.) The AppKit and UIKit frameworks process each event-loop iteration (such as a mouse down event or a tap) within an autorelease pool block. Therefore you typically do not have to create an autorelease pool block yourself, or even see the code that is used to create one. There are, however, three occasions when you might use your own autorelease pool blocks:
cocoa希望在自动释放池内执行代码,否则autoreleased的对象不能释放,你的程序会出现内存泄漏。如果你在自动释放池外部发送一条autorelease消息,cocoa会报错。AppKit 和 UIKit处理一些往复的事件循环在自动释放池中。像鼠标事件或者点击事件。因此你一般不需要自己创建自动释放池,或者甚至是看到用于创建自动释放池的代码。然而,有时候,三种场合下,你可能要创建自己的自动释放池。
1)If you are writing a program that is not based on a UI framework, such as a command-line tool.
如果你创建了一个不是基于UI框架的程序,例如命令行工具。
2)If you write a loop that creates many temporary objects.
如果你写了一个创建了很多临时变量的循环。
You may use an autorelease pool block inside the loop to dispose of those objects before the next iteration. Using an autorelease pool block in the loop helps to reduce the maximum memory footprint of the application.
你可能在下次循环之前使用一个自动释放池来释放那些变量。在循环中使用自动释放池来减少应用程序的峰值内存占用。
3)If you spawn a secondary thread.
如果你创建了一个二级线程。
You must create your own autorelease pool block as soon as the thread begins executing; otherwise, your application will leak objects. (See Autorelease Pool Blocks and Threads for details.)
你必须创建你的自动释放池在线程一开始执行的时候,否则,你的应用将会内存泄漏。
Use Local Autorelease Pool Blocks to Reduce Peak Memory Footprint。
使用自动释放池来减少峰值内存占用。
Many programs create temporary objects that are autoreleased. These objects add to the program’s memory footprint until the end of the block. In many situations, allowing temporary objects to accumulate until the end of the current event-loop iteration does not result in excessive overhead; in some situations, however, you may create a large number of temporary objects that add substantially to memory footprint and that you want to dispose of more quickly. In these latter cases, you can create your own autorelease pool block. At the end of the block, the temporary objects are released, which typically results in their deallocation thereby reducing the program’s memory footprint.
许多程序自动释放的临时对象。这些对象添加到程序的内存直到这个block结束。在大多数情况下,允许临时对象累计直到这个当前循环结束并不会引起内存占用大大占用。然而,在一些情况下,你可能会创建大量的临时对象,从而增加内存空间(这里的累计更多的是来不及释放)。你想要快速释放它们。在后边这种情况下,你可以创建自己的自动释放池。在自动释放池的最后,临时对象被release,这通常导致它们释放减少了内存占用。
The following example shows how you might use a local autorelease pool block in a for loop.
下边的例子显示在for循环中,你怎样利用自动释放池。
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. */
}
}
The for loop processes one file at a time. Any object (such as fileContents) sent an autorelease message inside the autorelease pool block is released at the end of the block.
这个for循环移除处理一个文件夹。在block最后,自动释放池中的所有对象都会发送一条autorelease消息。
注意:用类方法创建的对象,一般会把这个对象放入最近的自动释放池中。这就导致for循环中大量的对象放入了自动释放池中。导致局部出现了内存释放。对于这种情况最好不要等到让系统的自动释放池一次释放,需要自己创建一个自动释放池,这样的话我们就可以把局部变量提前释放了。
After an autorelease pool block, you should regard any object that was autoreleased within the block as “disposed of.” Do not send a message to that object or return it to the invoker of your method. If you must use a temporary object beyond an autorelease pool block, you can do so by sending a retain message to the object within the block and then send it autorelease after the block, as illustrated in this example
经过一个自动释放池之后,你应该把autoreleased的所有对象都给释放掉。不要发送消息给那个对象或者返回它给你的方法的调用者。如果你必须用一个超出自动释放池的临时变量,你可以发送一条retain消息给这个对象,然后在自动释放池之后给他发送一条autorelease消息,像下边例子一样:
Sending retain to match within the autorelease pool block the and sending autorelease to it after the autorelease pool block extends the life time of match and allows it to receive messages outside the loop and be returned to the invoker of findMatchingObject:.
在自动释放池中给match发送retain消息,在之后给match发送autorelease消息。这样允许他来接收循环之外的消息,并且可以作为返回参数。
Autorelease Pool Blocks and Threads
自动释放池和线程
Each thread in a Cocoa application maintains its own stack of autorelease pool blocks. If you are writing a Foundation-only program or if you detach a thread, you need to create your own autorelease pool block.
在cocoa程序中,每个线程都维护自己的自动释放池的栈结构。如果你正在写一个仅有Foundation的项目或者你分离线程,你需要自己的自动释放池。
If your application or thread is long-lived and potentially generates a lot of autoreleased objects, you should use autorelease pool blocks (like AppKit and UIKit do on the main thread); otherwise, autoreleased objects accumulate and your memory footprint grows. If your detached thread does not make Cocoa calls, you do not need to use an autorelease pool block.
如果你的程序或者线程长期存在,那么潜在的会存在大量的需要autoreleased的对象。你应该使用自动释放池,像AppKit 和 UIKit在主线程做的那样。否则,会堆积占用大量的内存。如果你的耳机线程不需要调用call,你不需要使用自动释放池。
Note:If you create secondary threads using the POSIX thread APIs instead o fNSThread, you cannot use Cocoa unless Cocoa is in multithreading mode. Cocoa enters multithreading mode only after detaching its first NSThread object. To use Cocoa on secondary POSIX threads, your application must first detach at least one NSThread object, which can immediately exit. You can test whether Cocoa is in multithreading mode with theNSThreadclass method isMultiThreaded.
注意:如果你用POSIX线程API创建了一个辅助线程,你不能使用cocoa。除非cocoa在多线程。cocoa只有在分离他的第一个线程对象之后。为了在辅助线程使用cocoa,你的程序必须分理出一个线程对象,这个线程对象可以立即停止。你可以检测cocoa是否处于多线程模式中。