Autorelease pools 官方文档
翻译自:
Autorelease pools提供了一个延迟向对象发送release消息的机制。当你想放弃一个对象的所有权,但是又不想这个对象马上被释放时(比如当你从一个方法中返回一个对象),这种机制是有用的。一般你不需要创建自己的autorelease pools,但是有的时候你必须自己创建autorelease pools,有的时候自己创建autorelease pools会带来便利。
关于Autorelease pools
一个autorelease pool是一个NSAutoreleasePool的实例,它包含收到autorelease消息的对象。当一个autoreleasepool被销毁的时候,它向所包含的每个对象发送一个release消息。一个对象可以放入autorelease pool多次;一个对象每次被放入pool中时都会收到一个release消息(发送一个autorelease消息)。
Autorelease pools以栈的形式进行组织,这通常被称为嵌套的方式。如果你创建了一个新的autorelease pool,它被添加到栈的顶端。当pools被销毁的时候,它们被从栈中移除。当一个对象发送一个autorelease消息时,它被添加到当前线程的Autorelease pools的最顶端的pool中。
Cocoa总是期望一个autoreleasepool是可用。如果一个pool是不可用的,被自动释放的的对象最终不会被释放,这样你的应用就会泄露内存。当一个pool不可用时,如果向一个对象发送autorelease消息,Cocoa会记录一个适当的错误信息。在每一个事件循环(event-loop)开始的时候(比如鼠标按下事件或者一个手势),AppKit和UIKit框架会自动地创建一个pool,并且在事件处理结束时销毁这个pool。(译者注:这个是object-c内存管理的一个核心)因此,一般你不需要自己创建一个pool,甚至没有必要去看创建pool的代码。然而,这里有3中情况你应该创建自己的autorelease pools:
l 你写的程序不是基于UIFramework,比如一个命令行工具。
l 你写了一个循环,里面创建了大量的临时变量。
在下次事件循环之前,你可以在这个循环中创建一个autorelease pool用于处理这些临时变量。在循环中使用autorelease pool帮助降低应用程序占用的内存峰值。
l 你生成了一个线程。
线程一开始执行,你就必须创建你自己的autorelease pool;不然,你的应用就会泄露对象。(“Autorelease Pools and Threads”查看更多细节)
你使用alloc和init消息创建一个NSAutoreleasePool对象,使用drain消息销毁这个对象。如果你向一个autorelease pool发送autorelease或retain消息则会触发异常。想理解消息release和drain的不同,可以看“Garbage Collection。“一个autorelease pool应该总是在”其被创建的上下文”(比如一个方法或函数调用中,或者一个循环中)中被销毁。
使用Local AutoreleasePools降低内存峰值
很多程序创建自动释放的临时变量。这些变量放置在程序的内存中直到pool被销毁。你可以使用local autorelease pools帮助降低内存峰值。当你的pool销毁的时候,这些临时对象被释放,从而降低程序的内存峰值。
下面的例子展示一个循环中使用localautorelease pool的一个方法
NSArray *urls = <# An array of file URLs #>;
for (NSURL *urlin urls) {
NSAutoreleasePool *loopPool = [[NSAutoreleasePoolalloc]init];
NSError *error =nil;
NSString *fileContents = [[[NSStringalloc]initWithContentsOfURL:url
encoding:NSUTF8StringEncodingerror:&error]autorelease];
/* Process the string, creating and autoreleasing more objects. */
[loopPool drain];
}
For循环一次处理一个文件。一个NSAutoreleasePool对象在循环的开始被创建,在循环的末尾被销毁。因此,这个循环中任何一个发送autorelease消息的对象都会被放到这个loopPool中,当loopPool在循环的最后被销毁时这些对象被释放。
一个autorelease pool被销毁后,你应该认为这个pool被销毁前存放的autoreleased对象都被销毁掉了。不要再向之前在pool中的对象发送消息或把它返回给你的方法的调用者。如果你必须在一个autorelease上下文之外使用一个临时对象,可以像下面的例子描述的那样,在这个上下文中向这个对象发送一个retain消息,然后在这个pool被销毁后向这个对象发送一个autorelease消息。
– (id)findMatchingObject:(id)anObject {
id match = nil;
while (match == nil) {
NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init];
/* Do a search that creates a lot of temporary objects. */
match = [self expensiveSearchForObject:anObject];
if (match != nil) {
[match retain]; /* Keep match around. */
}
[subPool drain];
}
return [match autorelease]; /* Let match go and return it. */
}
在subpool起作用的时候,向match发送一个retain消息,在subpool销毁后,向它发送一个autorelease消息,通过这样,match从subpool转移到subpool之前起作用的pool中。这样扩展了match的生命周期并且使它可以在循环外接收消息、返回给findMatchingObject:的调用者。
AutoreleasePools和线程
在Cocoa应用程序中,每个线程管理它自己的NSAutoreleasePool的栈。当一个线程终止时,它自动的释放所有与它关联的autorelease pool。如果你写一个只使用Foudation框架的应用或者你自己创建一个线程时,你需要创建自己的autorelease pool。
如果你的应用或线程生命周期很长并且可能会生成很多自动释放的对象,那么你应该周期的销毁和创建autorelease pool(就像Kit框架在主线程开始所做的那样)。
否则的话,自动释放的对象会堆积,你的应用的内存峰值会增长。如果你自己创建的线程做Cocoa相关的调用,你就不需要创建autorelease pool。
注意:
如果你使用POSIX threadAPIs而不是使用NSThread创建一个线程,你就不能使用Cocoa,包括NSAutoreleasepool,除非Cocoa是在多线程模式。Cocoa 只有在创建它的第一个分离的线程对象后才会进入多线程模式。为了在随后创建的POSIX线程中使用Cocoa,你的应用必须首先创建一个分离的NSThread对象,并且这个分离的线程会马上退出。你可以使用NSThread的类方法isMultiThreaded测试Cocoa是否在多线程模式。
AutoreleasePools的作用域和嵌套的Autorelease Pools的实现
通常说autorelease pool是嵌套的,也可以认为嵌套的autoreleasepool是放在一个栈上,最内层的autorelease pool是放在栈顶。程序中的每个线程管理一个autorelease pools的栈。当你创建一个autorelease pool时,它被放到当前线程的autorelease pool的栈的顶端。当一个对象发送一个autorelease消息或者当它做为addObject的参数传递时,它总是被放在autorelease pool栈的顶端的aurelease pool中。
一个autorelease pool是否起作用与它在栈中的位置有关。栈顶端的pool是自动释放的对象被添加到的地方。如果一个新的pool被创建,那么当前最顶端的pool会变为不起作用的直到新创建的pool被销毁。(这样之前的pool又变为最顶端的pool)。当它被销毁的时候,它将永远不会再起作用。
如果你销毁一个非栈最顶端的autoreleasepool时,那么这个栈中所有在这个autorelease pool之上autorelease pool被销毁(会向它们中的所有对象发送release消息)。如果当你使用完一个autorelease pool而没有销毁它(一般不建议),这个pool会被销毁当它嵌套的autorelease pool被销毁的时候。
这个行为忽略掉了有异常的情况。如果一个异常发生了,线程突然退出当前上下文,这个pool关联的上下面文被销毁了。然而,如果那个pool不是位于线程栈最顶端的pool,那么这个pool上面的所有pool都会被销毁(这个过程会释放掉所有的对象)。这个pool下面的一个pool会成为栈顶autorelease pool。因为这样,所以异常处理不需要释放autorelease pool中的对象。对于异常处理没有必要也不值得向它的autorelease pool发送release消息,除非异常会重新触发这个异常。
Autorelease pools 官方文档的更多相关文章
- 【AutoMapper官方文档】DTO与Domin Model相互转换(上)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 2DToolkit官方文档中文版打地鼠教程(三):Sprite Collections 精灵集合
这是2DToolkit官方文档中 Whack a Mole 打地鼠教程的译文,为了减少文中过多重复操作的翻译,以及一些无必要的句子,这里我假设你有Unity的基础知识(例如了解如何新建Sprite等) ...
- 2DToolkit官方文档中文版打地鼠教程(二):设置摄像机
这是2DToolkit官方文档中 Whack a Mole 打地鼠教程的译文,为了减少文中过多重复操作的翻译,以及一些无必要的句子,这里我假设你有Unity的基础知识(例如了解如何新建Sprite等) ...
- 2DToolkit官方文档中文版打地鼠教程(一):初始设置
这是2DToolkit官方文档中 Whack a Mole 打地鼠教程的译文,为了减少文中过多重复操作的翻译,以及一些无必要的句子,这里我假设你有Unity的基础知识(例如了解如何新建Sprite等) ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(中)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(下)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- Ionic2系列——Ionic 2 Guide 官方文档中文版
最近一直没更新博客,业余时间都在翻译Ionic2的文档.之前本来是想写一个入门,后来觉得干脆把官方文档翻译一下算了,因为官方文档就是最好的入门教程.后来越翻译越觉得这个事情确实比较费精力,不知道什么时 ...
- Kotlin开发语言文档(官方文档)-- 目录
开始阅读Kotlin官方文档.先上文档目录.有些内容还未阅读,有些目录标目翻译还需琢磨琢磨.后续再将具体内容的链接逐步加上. 文档链接:https://kotlinlang.org/docs/kotl ...
- 一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍
我们在前一篇文章微软新神器-Power BI,一个简单易用,还用得起的BI产品中,我们初步介绍了Power BI的基本知识.由于Power BI是去年开始微软新发布的一个产品,虽然已经可以企业级应用, ...
随机推荐
- mysqlnd cannot connect to MySQL 4.1+ using old authentication
报这个错误主要是因为mysql使用了老的密码格式,而程序要求使用新的格式导致的,解决办法: SET old_passwords = 0; UPDATE mysql.user SET Password ...
- 【188】HTML + CSS + JS 学习网站
RGB 取色器 HTML 参考手册 CSS 参考手册 HTML 在线测试工具 上面源码(博客园 - HTML): <style><!-- p.bg_gr ...
- 12_传智播客iOS视频教程_注释和函数的定义和调用
OC的注释和C语言的注释一模一样.它也分单行注释和多行注释. OC程序里面当然可以定义一个函数.并且定义的方式方法和调用的方式方法和我们C语言是一模一样的.OC有什么好学的?一样还学个什么呢? 重点是 ...
- linux简单技巧和怎么样进入root用户
1.使用shell的Tab键自动补全 Tab在linux命令行输入中可以自动完成.在linux 命令行中使用Tab键会极大提高输入效率2.使用shell的历史记录 shell会记录用户执行命令的历史记 ...
- ExtJS 4 MVC 官方示例
参考原文翻译地址:http://www.showframework.com/2012/07/extjs-mvc-architecture/ 效果图 代码结构: 源代码下载: http://hot.ba ...
- bzoj 4385: [POI2015]Wilcze doły【单调栈】
对于每个i,以它为左端点的最优右端点一定是单增的,所以用单调栈维护 具体的,单调栈里放的是和单调的长为d的子段,然后枚举右端点,如果这段的和-当前长为d子段最大的和大于p的话,左端点右移同时注意单调栈 ...
- Activiti6.0教程 Service用途剖析 (二)
这节我们学习下Activiti的7大对象,首先我们从ProcessEngine接口开始看. /* Licensed under the Apache License, Version 2.0 (the ...
- shiro之IniRealm
Shiro认证过程 创建SecurityManager--->主体提交认证--->SecurityManager认证--->Authenticsto认证--->Realm验证 ...
- [Usaco2006 Open]County Fair Events 参加节日庆祝
Description Farmer John has returned to the County Fair so he can attend the special events (concert ...
- poj 1511 Invitation Cards spfa 邻接矩阵
题目链接: http://poj.org/problem?id=1511 题目大意: 这道题目比较难理解,我读了好长时间,最后还是在队友的帮助下理解了题意,大意就是,以一为起点,求从一到其他各点的最短 ...