参考:http://www.jianshu.com/p/1b66c4d47cd7
在每一个Runloop中,系统会隐式创建一个Autoreleasepool;
(一个UI事件,Timer call, delegate call, 一个鼠标事件,键盘按下(MAC OSX),或者iphone上的触摸事件,异步http连接下后当接收完数据时,都会创建autoreleasepool???)
问题
-
auto release 对象什么时候释放?
参考:http://blog.sunnyxx.com/2014/10/15/behind-autorelease/
在没有加入autorelease pool情况下,autorelease对象是在当前的runloop迭代结束时释放的; -
autoreleasepool中的对象,release将延迟到什么时候执行?
1.当前autoreleasepool结束后,该pool中所有对象会被release;
2.手动调用drain释放; -
系统是什么时候释放的?
"The Application Kit creates an autorelease pool on the main thread at the beginning of every cycle of the event loop".
在每一个事件周期的开始,系统会自动创建一个自动释放池,在每一个事件周期的结尾,系统会自动销毁这个自动释放池;
ARC之前,会在下一轮runloop时,释放这个auto-release pool? -
autoreleasepool 何时需要手动创建?
1.当你在主线程开启其他线程;//大多数情况下不需要自己创建线程,可以使用系统的GCD和NSOperation;
2.在短时间内制造了大量自动释放对象时,及时销毁有助于内存资源合理利用; -
ARC 中 autoreleasepool
ARC并不是舍弃了autoreleasepool,而是在编译阶段帮你插入必要的retain/release/autorelease的代码调用;
ps: 对象并不是自动被加入到当前pool中,而是需要对象发送autorelease消息; -
ARC下,_weak指向对象被释放了,那么_weak会被自动设置为nil,那么runtime是如何做到这一点的那?
在内存中维护一张weak表
{
id __weak obj1 = obj;
}
/* 编译器模拟代码 */
id obj1;
objc_initWeak(&obj1, obj);
objc_destroyWeak(&obj1);
一个对象地址可以对应很多个_weak变量地址,当一个对象被析够时,那么他在weak表中所指向的_weak变量就会被置为nil,然后再weak表中删除该记录;
由于使用weak变量会造成以上系统开销,所以要仅在需要时才使用;
- ARC下如何获取retainCount
使用_objc_rootRetainCount(obj);
实现原理
详情可以参考autoreleasepool的objc源码
@autoreleasepool {} 实际上是两个函数的调用:
objc_autoreleasePoolPush
objc_autoreleasePoolPop
这两个函数都调用了AutoreleasePoolPage类中的方法,也就是说他们是通过AutoreleasepoolPage实现的;
阅读源码可知,AuoreleasePoolPage的定义中有如下属性:
magic_t const magic; //校验结构完整
id *next; //指向栈顶
pthread_t const thread; //指向当前线程
AutoreleasePoolPage * const parent; //指向父节点
AutoreleasePoolPage *child; //指向子节点
uint32_t const depth; //链表的深度,即链表节点的个数
uint32_t hiwat; //hight water mark 最高水位标记,栈对象做多时候的个数
这个类有parent跟child节点,可以推断出这个一个双向链表的节点,而实际上Autoreleasepool的内存结构就是一个双向链表;
也就是说一个线程的autoreleasepool就是一个指针栈,栈中存放的指针指向加入其中的需要release的对象或者POOL_SENINEL(哨兵对象, 用不分割autoreleasepool);
哨兵对象是在入栈时加入的一个autoreleasepool的标记,当autoreleasepool进行出栈时,每一个比这个哨兵对象后进栈的对象都会release;
这个栈是由一个以page为节点的双向链表组成,page根据需求进行增减;若是一个page已存满autorelease对象,则新建一个page;
autorelease函数和push函数一样,都是通过autoreleaseFast函数想自动释放池中添加一个对象,不过push函数的入栈是一个哨兵对象,而autoreleas函数入栈的是需要加入autoreleasepool的对象;
网友评论