问题1 是否所有的的对象加入了autoreleasepool?
有时候会听到这样的回答。ARC下一个对象创建的时候就会加入到自动释放池,这显然是不对的。
只有需要延迟释放的对象,才会加入到autoreleasepool,那么什么是延迟释放的对象。待会我会提到。
在MRC下 [obj retain] 计数为1, [obj release] 计数为0。obj指向的对象就释放了。obj指针还在。那么在ARC是怎么样的,我们都知道ARC其实也会有retain,release的操作,只是他是在编译期自动插入在合适的地方。
问题2 什么对象会加入autoreleasepool?
在MRC下调用了 autorelease自然会加入到释放池。那么ARC呢?
内存管理有四个原则(MRC和ARC都适用)
1 自己生成的对象,自己所持有(alloc,new,copy,mutablecopy)
2 非自己生成的对象,自己也能持有(retain,在arc下如果A引用了B,就会对B自动retain)
3 不再需要自己持有的对象时对其释放(release)
4 非自己持有的对象无法释放。
5 dealloc是销毁。retain 和release 两个方法分别是将reference counter 加1和减1。
当使用release方法当reference counter值为0时会自动使用dealloc方法。
A NSString *str = [NSString alloc] init];
B NSString *str = [NSString xxx类方法];
这两种获取对象的方式的不同之处就是在A的对象是自己生成的。B的对象是类方法返回的。类方法的方法一般如下。
(NSString *)xxx类方法{
NSString *str = [NSString alloc] init];
//C
return str;
}
如果我要释放这个对象就需要在C这个位置释放。但是如果我释放了。B这个位置及获取不到str对象了。所以才需要延迟释放,才需要一个自动释放池。
问题3 加入了autoreleasepool中的对象什么时候释放?
在没有手加autorelease Pool的情况下,autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop。
最后会自动对其中的对象执行一次release。 暂时不写autoreleasepage的结构。
。只想问一下这里说的迭代时机是哪一个时机?
如果在迭代时机过早,为什么不会释放了还需要使用的对象。
问题4 NSRunloop多久一次迭代,如何迭代?
NSRunloop可以简单理解成如下循环
1(等待消息) -> 2(将要处理消息) -> 3(处理消息) -> 4(消息处理完成) -> 1(等待消息)
其中,autoreleasePool 在 4 (消息处理完成) 这个阶段进行释放。在一个消息处理中,无论包含多少层函数调用,也一直处于 3 (处理消息) 这个阶段当中。因此在当前消息循环内,放到 autoreleasePool 的对象会一直生效,并不会被释放。
所以,一个消息未结束,他想关联的对象就不会被释放掉。消息结束了,那我的事件也已经处理完毕了,对象也用不到了。
问题5 子线程中的autoreleasepool是什么机制?
子线程默认是没有NSRunLoop的,那么子线程中的自动释放池的对象是如何操作的?
如果获取不到autoreleasePoolpage,就会创建一个autoreleasePoolNopage。
结构下回分解。
测验:
for (100000times 循环){
NSString *str = [NSString alloc] init];
}
会出现内存峰值吗?