" ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有alloc,new,[mutable]copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁. "网摘
自从ARC以后 我们不需要手动释放内存 但是有时候 我们仍然需要手动释放,以便更加精准的管理内存问题.
这里 就用到@autoreleasepool{} //自动释放内存池 “释放池”
(1)@autoreleasepool{} 按栈的顺序释放内存 销毁对象, 可以嵌套使用
(2)@autoreleasepool{} 相当于 做 autorelease / release 操作,如果把已经autorelease / release 的对象做 释放池操作 就会报野指针错误. (ARC 好像这个问题就很少有了吧…)
举例子
(1)循环创建临时变量 或者说 短时间内创建大量变量 应该考虑使用 @autoreleasepool{}
这个例子 真是不胜枚举啊
- (void)viewDidLoad { [super viewDidLoad]; [self test2]; } - (void)test2 { CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); for (int i = 0; i < 10000000; ++i) { @autoreleasepool { MethodDetailMusic *music = [[MethodDetailMusic alloc]init]; music.title = @"haha"; // NSLog(@"%@", music.title); } } NSLog(@"end - %f", CFAbsoluteTimeGetCurrent() - start); }
(1)是否有 @autoreleasepool {} 拿 Leak工具 跑了一次 看对比截图
看前面几个惊险的MB 就看出差别了吧
(2)@autoreleasepool {} 放在循环体外 和循环体内还是有很大差别的
//10000
2016-08-18 11:44:44.558 LearningTheroyDemo[40012:6355283] end - 0.002388
2016-08-18 11:45:49.970 LearningTheroyDemo[40032:6356878] end - 0.002540
//10000000(从这可以看出枚举量越大 效率差别越明显)
2016-08-18 11:47:30.521 LearningTheroyDemo[40071:6359862] end - 2.655450
2016-08-18 11:48:14.521 LearningTheroyDemo[40080:6361041] end - 2.932974
(2) 自己创建的线程 "detach thread", 有相对来说 很多需要释放的对象,应该使用@autoreleasepool{} 否则内存会升高,但是 如果这个非关联线程 "detach thread"没有使用到cocoa的相关调用 就不必创建 autorelease pool.
第二段,大概是说如果创建POSIX 线程 做二级线程 这个就不能使用 cocoa ,不能使用 @autoreleasepool{}, 除非 cocoa
在多线程里面,并且是一级线程里面的对象.所以 在二级POSIX线程里面要使用cocoa必须有这个所谓的一级线程,并且要立即销毁.所以 你要使用 cococa 要确保是在多线程里面 如何判断 bla bla.
我觉得 我翻译的还行 没出什么原则的bug 网上好多帖子 说的 不是不对 就是不准 , 根本没说明白 detach thread 里面 到底 能不能用 @autoreleasepool{} ? 简单的来说 如果 创建了 很多需要释放的对象 就可以用啊 ,因为 我们常用的多线程(NSOperation NSthread GCD ) 是满足需求没有例外的 ,就是 官方文档提到的这个 "POSIX thread" ( 是调用pthread_create来创建的线程 C语言底层部分的知识了此处不再扩展,需要深究时候及时学习)不能使用@autoreleasepool{},但是也给了一个 处理方案...
If you are making Cocoa calls outside of the Application Kit’s main thread—for example if you create a Foundation-only application or if you detach a thread—you need to create your own autorelease pool.
If your application or thread is long-lived and potentially generates a lot of autoreleased objects, you should periodically drain and create autorelease pools (like the Application Kit does on the main thread); otherwise, autoreleased objects accumulate and your memory footprint grows. If, however, your detached thread does not make Cocoa calls, you do not need to create an autorelease pool.
Note
If you are creating secondary threads using the POSIX thread APIs instead of NSThread
objects, you cannot use Cocoa, including NSAutoreleasePool
, 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 the NSThread
class method isMultiThreaded
.
参考
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/
http://www.cnblogs.com/CoderAlex/p/5232357.html