1. 在主线程的 NSRunLoop 对象(在系统级别的其他线程中应该也是如此,比如通过 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 获取到的线程)的每个 event loop 开始前,系统会自动创建一个 autoreleasepool ,并在 event loop 结束时 drain 。我们上面提到的场景 1 中创建的 autoreleased 对象就是被系统添加到了这个自动创建的 autoreleasepool 中,并在这个 autoreleasepool 被 drain 时得到释放。
2. 每一个线程都会维护自己的 autoreleasepool 堆栈。换句话说 autoreleasepool 是与线程紧密相关的,每一个 autoreleasepool 只对应一个线程。
1). 只有在自动释放池中调用了对象的autorelease方法,这个对象才会被存储到这个自动释放池之中.
如果只是将对象的创建代码写在自动释放之中,而没有调用对象的autorelease方法.是不会将这个对象存储到这个自动释放池之中的.
2). 对象的创建可以在自动释放池的外面,在自动释放池之中,调用对象的autorelease方法,就可以将这个对象存储到这个自动释放池之中.
将1个对象存储到自动释放池中,最重要的步骤
调用对象的autorelease方法,这句代码一定要放在池子中.
3). 当自动释放池结束的时候.仅仅是对存储在自动释放池中的对象发送1条release消息 而不是销毁对象.
4). 如果在自动释放池中,调用同1个对象的autorelease方法多次.就会将对象存储多次到自动释放池之中.
在自动释放池结束的时候.会为对象发送多条release消息.那么这个时候就会出现僵尸对象错误.
所以,1个自动释放池之中,只autorelease1次,只将这个对象放1次, 否则就会出现僵尸对象错误.
5). 如果在自动释放池中,调用了存储到自动释放中的对象的release方法.
在自动释放池结束的时候,还会再调用对象的release方法.
这个时候就有有可能会造成野指针操作.
也可以调用存储在自动释放池中的对象的retain方法.
6). 将对象存储到自动释放池,并不会使对象的引用计数器+1
所以其好处就是:创建对象将对象存储在自动释放池,就不需要在写个release了.
7). 自动释放池可以嵌套.
调用对象的autorelease方法,会讲对象加入到当前自动释放池之中
只有在当前自动释放池结束的时候才会像对象发送release消息.
默认主线的运行循环(runloop)是开启的,子线程的运行循环(runloop)默认是不开启的,也就意味着子线程中不会创建autoreleasepool,所以需要我们自己在子线程中创建一个自动释放池。(子线程里面使用的类方法都是autorelease,就会没有池子可释放,也就意味着后面没有办法进行释放,造成内存泄漏。)