OC释放对象有两种方式,一种是调用release方法,使其保留计数立即递减,另一种是调用autorelease方法,将其加入“自动释放池”中。自动释放池用于存放那些需要在稍后某个时刻释放的对象。清空自动释放池时系统会像其中的对象发送release消息。自动释放池机制就像“栈”一样。系统创建好自动释放池之后将其推入栈中,而清空自动释放池,则相当于将其从栈中弹出。在对象上执行自动释放操作,就等于将其放入栈顶的那个池子里。应用程序中一般无须担心自动释放池的创建问题,系统会自动创建一些线程,比如说主线程或是GCD机制中的线程,这些线程默认都有自动释放池,每次执行“事件循环”时,就会将其清空。因此,不需要自己来创建“自动释放池块”。
创建自动释放池的语法:
@autoreleasepool {
//...
}
花括号定义了自动释放池的范围。自动释放池于左花括号处创建,并与对应的右花括号处自动清空。位于自动释放池内的对象,将在此范围末尾处收到release消息。
例如如下代码:
NSArray *databaseRecords = /*...*/;
NSMutableArray *people = [NSMutableArray new];
for (NSDictionary *record in databaseRecords) {
EOCPerson *person = [[EOCPerson alloc] initWithRecord:record];
[people addObject:person];
}
for循环中创建的对象,会持续加入到自动释放池中,等待系统稍后将其释放,然而自动释放池要等线程执行下一次事件循环时才会清空。这就意味着这些对象依然存活,在for循环不断执行的时候,应用程序内存就会持续上涨,这种情况不甚理想,尤其循环长度无法预知的情况下。增加一个自动释放池就可以解决此问题。如果把循环内的代码包裹在“自动释放池块”中,那么在循环中自动释放的对象就会放在这个池子中,而不是线程的主池子里面。例如:
NSArray *databaseRecords = /*...*/;
NSMutableArray *people = [NSMutableArray new];
for (NSDictionary *record in databaseRecords) {
@autoreleasepool {
EOCPerson *person = [[EOCPerson alloc] initWithRecord:record];
[people addObject:person];
}
}
新增这个自动释放池块可以减少内存峰值,因为系统会在块的末尾把某些对象回收掉。
是否应该用池来优化效率,完全取决于具体的应用程序。首先得监控内存用量,判断其中有没有需要解决的问题,如果没完成这一步,那就别急着优化。尽管自动释放池块的开销不太大,但毕竟还是有的,所以尽量不要建立额外的自动释放池。
总结:
1.自动释放池排布在栈中,对象收到autorelease消息后,系统将其放入最顶端的池里。
2.合理运用自动释放池,可降低应用程序的内存峰值。
3.@autoreleasepool这种新式写法能创建出更为轻便的自动释放池。