文档翻译-NSAutoreleasePool

苹果官方文档NSAutoreleasePool

NSAutoreleasePool这个类被用于支持Cocoa的引用计数内存管理机制. 当一个autorelease pool被drain(释放)的时候会对池子里的对象发送一条release的消息.

如果你的工程是ARC的, 那么你不能直接使用autorelease pool, 作为代替, 你应该使用@autoreleasepool {} 这个block. 官方代码如下 :

@autoreleasepool

Ps : 官方文档说明, 使用@autoreleasepool这个block比NSAutoreleasePool更高效!并且在MRC环境下同样适用

在引用计数的环境下(跟垃圾收集机制不同), 一个对象入(NSAutoreleasePool对象)前均会收到一条autorelease的消息, 当池子被销毁的时候会发送一条release的消息给这些对象. 因此, 发送autorelease消息来代替发送release消息可以延长池中对象的生命周期, 直到池子被销毁. (这种情况下对象的生命周期有可能更长因为有可能有别的对象引用着这个池中的对象). 另外值得注意的是, 一个对象可以反复加入同一个池子中, 只是它每次入池之前都会先收到release消息.

在引用计数的环境下, Cocoa希望总是至少有一个可用的autorelease pool在程序中, 否则, 收到过autorelease的对象将不会对应地收到release的消息而导致内存泄漏. 在这种情况下, 你的程序一般会打印一些适当的警告信息.

Application Kit在开始每一个事件循环之前都会在主线程创建一个autorelease pool, 并且在事件循环结束的时候销毁它. 所以, 当处理完一个时间之后就会释放掉生成的autorelease对象. 如果你使用Application Kit的话, 一般来说你不需要手动创建autorelease pool. 但是如果你的应用在一个事件循环里面创建了大量的autorelease对象的话, 这时如果你能主动地创建一些局部的autorelease pools, 对减少内存占用的峰值具有一定的帮助.

用alloc-init方法创建一个NSAutoreleasePool对象和drain方法来处理它. 因为你不能retain一个autorelease pool, 所以drain方法相当于释放它的内存. 你应该在同一个环境, 上下文(调用创建这个池的同一个方法, 函数或者循环体)drain一个autorelease pool.

每一个线程(包括主线程)都维护着它自己的NSAutoreleasePool对象的栈. 当一个新的池子被创建的时候, 它被压到栈顶上. 当池子被释放内存时, 它们就会被移除出栈. autorelease对象被放在当前线程的栈顶池子中. 当一个线程终止的时候, 它会自动地drain掉所有跟它有关联的池子.

Threads

如果你正在Application Kit的主线程外边making Cocoa call, 例如, 如果你创建了一个Foundation-only 的应用或者你分离了一个线程, 你需要自己创建你自己的autorelease pool.

如果你的应用或者线程是长期存在的并且有可能生成很多autorelease对象, 你应该定期地drain和创建autorelease pools(就像Application Kit在主线程做的那样); 否则, autorelease对象会在内存中堆积造成内存占用攀登. 当然, 如果你分离的线程并没有make Cocoa call, 你就不需要去创建一个autorelease pool.

NOTE
如果你用POSIX thread APIs创建第二个线程来代替NSThread对象的话, 你不能使用Cocoa, 包括NSAutoreleasePool, 除非Cocoa处于多线程模式. Cocoa只有在它分离第一个NSThread对象之后才会进入多线程模式.要想在第二个POSIX线程中使用Cocoa, 你的应用必须至少分离了一个可以马上退出的NSThread对象. 你可以利用NSThread的类方法isMultiThreaded来测试Cocoa是否处于多线程模式.

Garbage Collection

垃圾收集的环境下, autorelease pool没有存在的必要. 你可能想写一个同时可以工作在垃圾收集引用计数两个环境下的框架. 这种情况下, 你可以使用autorelease pools去暗示收集器, 此次收集是否恰当. 在垃圾收集的环境下, 给pool发送drain信息, 如果有必要的话就会触发垃圾收集池进行垃圾收集. 然而, 给pool发送release等于什么也不做. 在引用计数的环境下, drain相当于release. 综上, 一般都会发送drain消息而不是release.

Managing a Pool

release
drain
autorelease
retain

release

释放并且从栈中弹出该消息的接收者

  • (void)release
    说明 :
    在引用计数的环境下, 因为autorelease pool不能retain, 这个方法导致pool会被释放内存. 当一个autorelease pool被释放内存的时候, 他就会发送一条release给所有池中的autorelease对象. 如果一个对象被反复添加到相同的池中数次, 那么当池被释放的时候那么它每次添加到池中时都会收到一条release消息.
    但是在垃圾收集的环境下, 这个方法不做任何事.
    特殊情况
    你应该用drain而不是release

drain

引用计数的环境下, 释放并从栈中弹出这条消息的接收者;
垃圾收集的环境下, 如果上次分配的内存集合已经大于当前的阈值, 就触发垃圾收集.

  • (void)drain
    说明 :
    在引用计数的环境下, 这个方法等同于release. 因为autorelease pool不能retain, 所以这条消息会导致pool被释放内存. 当一个autorelease pool被释放内存的时候, 他就会发送一条release给所有池中的autorelease对象. 如果一个对象被反复添加到相同的池中数次, 那么当池被释放的时候那么它每次添加到池中时都会收到一条release消息.
    特殊情况
    垃圾收集的环境下, release消息是一个空方法, 所以不管你的代码运行在什么环境下, 使用drain都是最佳方法, 除非你不想暗示收集器做事(在垃圾收集环境下).
    有效性 :
    OS X v10.4及之后有效

autorelease

增加一个例外

  • (id)autorelease
    返回值
    自身
    说明 :
    引用计数的环境下, 这个方法增加一个例外.

retain

同autorelease

Adding an Object to a Pool

+ addObject :

在当前线程下往有效的autorelease pool里添加一个给定的对象
+(void)addObject : (id)object
说明 :
相同的对象有可能会被重复加进有效的池子里, 当池子被释放内存时, 它每次被加进池子时都会收到release消息.
一般你不能显式地调用这个方法, 你应该调用对象的autorelease方法
有效性 :
OS X v10.0及以后有效

- addObject :

同上, 这是对象方法

Debugging

+ showPools

显示当前线程下autorelease pool栈的状态
+(void)showPools // objc
class func showPools() // swift

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容