重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
1,ARC的本质
为武宁等地区用户提供了全套网页设计制作服务,及武宁网站建设行业解决方案。主营业务为成都网站设计、做网站、成都外贸网站建设公司、武宁网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!ARC本质是NSAutoreleasePool的直接应用,
@autorelease{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
其实是:
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
int iRet = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
[pool release];
然后,各种allocrelease后,对应refcount都设置成0,在出自己的引用范围后,就背nsautoreleasepool自动的释放掉,如下:
NSString* str = [[[NSString alloc] init] autorelease];
.......
其中str已经进行了autorelease,当结束生命周期后,str直接释放掉。
2,NSAutoreleasePool的原理
AutoreleasePoolPage是一个C++实现的类。
typedef struct{magic_t const magic;id* next;pThread_t* thread;AutoreleasePoolPage* Parent;AutoreleasePoolPage* Child;uint32_t const depth;uint32_t hiwat;}其中:1,magic是魔术数字,划分内存边界,数据结构起始处;2,next,是指向该AutoreleasePool的边界;3,thread, 是该AutoreleasePool的线程,每个线程有自己的AutoreleasePool; 4,Parent、child,用于建立链表,一个AutoreleasePool不一定足够; 每个NSAutoreleasePool都是4096bytes,不够的就申请新的NSAutoreleasePool,用child, parent连接起来,见上图: 1,“类实例所占内存”就是数据接口NSAutoreleasePool的空间; 2,“id objx”, 就是各个申请的对象指针; 3,next,指的是堆栈顶处; 对象是如何申请的?图中的情况,这一页再加入一个autorelease对象就要满了(也就是next指针马上指向栈顶),这时就要执行上面说的操作,建立下一页page对象,与这一页链表连接完成后,新page的next指针被初始化在栈底(begin的位置),然后继续向栈顶添加新对象。
所以,向一个对象发送- autorelease消息,就是将这个对象加入到当前AutoreleasePoolPage的栈顶next指针指向的位置
对象是如何释放的? 每当进行一次objc_autoreleasePoolPush调用时,runtime向当前的AutoreleasePoolPage中add进一个哨兵对象,值为0(也就是个nil),那么这一个page就变成了下面的样子:objc_autoreleasePoolPush的返回值正是这个哨兵对象的地址,被objc_autoreleasePoolPop(哨兵对象)作为入参,于是:
1.根据传入的哨兵对象地址找到哨兵对象所处的page
2.在当前page中,将晚于哨兵对象插入的所有autorelease对象都发送一次- release消息,并向回移动next指针到正确位置
3.补充2:从最新加入的对象一直向前清理,可以向前跨越若干个page,直到哨兵所在的page
刚才的objc_autoreleasePoolPop执行后,最终变成了下面的样子:
嵌套的AutoreleasePool
知道了上面的原理,嵌套的AutoreleasePool就非常简单了,pop的时候总会释放到上次push的位置为止,多层的pool就是多个哨兵对象而已,就像剥洋葱一样,每次一层,互不影响。