Objc内存管理之MRC

来源:互联网 发布:淘宝卖家发什么快递好 编辑:程序博客网 时间:2024/06/06 13:57

Objc中的内存管理,也就是引用计数。引用计数顾名思义就是对引用计数(这tmd不是废话吗),对一个对象进行引用计数的目的就是来决定什么时候废弃对象,看似复杂的的内存管理的实质也就是这些(所谓的废话)。

MRC即手动引用计数:

首先我们举个栗子(��):

我们都要回宿舍(如果你不去open room,笔者是一位品性良好的小学生),第一个回宿舍的时候需要开门,最后一个回宿舍的需要关门,当宿舍里面有人的时候你不能锁门(被锁宿舍里面是一件非常蛋疼的事情,而且真的非常疼)。为判断是否有人在宿舍,我们需要计数(记录在宿舍里的人数)。

开门:计数从0变为1;

之后有人进门:计数+1;

有人出宿舍:计数-1;

最后一个人离开宿舍:计数变为0(我数学不好,但加减法还是可以的  哈哈);

这个例子如何与Objc中的对象计数联系起来呢?

第一个人开门并进入宿舍:生成对象,引用计数变为1;

有人进来:    持有对象,引用计数加   1;

有人离开:    释放对象,引用计数减   1;

关门:    引用计数此时为0,废弃对象。

当然Objc中的内存管理比回宿舍更难(甚至比open room还要难),内存管理深似海,从此对象是路人,回宿舍这个��该一段落,接着往下看吧:

在MRC的内存管理模式下,与对变量的管理相关的方法有:retain,release和autorelease。

retain和release方法操作的是引用记数,当引用记数为零时,便自动释放内存。并且可以用NSAutoreleasePool对象,对加入自动释放池(autorelease调用)的变量进行管理,当drain时回收内存。

(1)      retain,该方法的作用是将内存数据的所有权附给另一指针变量,引用数加1,即retainCount+= 1;

(2)      release,该方法是释放指针变量对内存数据的所有权,引用数减1,即retainCount-= 1;

(3)      autorelease,该方法是将该对象内存的管理放到autoreleasepool中。

看到这里,retain和release是没问题,自动释放池又是什么鬼?不方不方,最后再搭理她。

听我说,自己生成的对象自己持有,跟着我读三遍:自己生成的对象自己持有,对,非常好。我们对持有这个名词不算陌生,拿刚刚回宿舍的栗子来解释这句话:第一个人开门进来,计数加一。

使用alloc,new,copy,mutableCopy名称开头的方法意味着自己生成的对象自己持有!!!

值得注意的是:copy和mutableCopy:这两个方法生成并持有对象的副本(也是自己生成并持有对象),二者的区别在于copy方法生成不可变更的对象,mutableCopy生成可变更的对象。

自己持有的对象一旦不再需要,则需要使用release方法释放。代码如下:

id obj = [[NSObject alloc] init];

//自己持有对象

//-旦不再需要该对象,必须释放

[obj release];

//释放对象

//对象一经释放绝对不可以访问

OK这个和回宿舍的栗子还是完全吻合的,还有一种现象:

非自己生成的对象,自己也能持有:

上述说到,用alloc、new、copy、mutableCopy方法取得的对象自己生成并持有,除这四个方法取得的对象,非自己生成,故不是对象的持有者。

看如下代码:

id obj = [NSMutableArray  array];

/*取得非自己生成的对象

自己不持有对象,只是取得对象的存在*/


如果想取得对象的存在,可以使用:

[obj retain];


OK这两种情况已经说完了,如果想继续深入了解,可以看源码了,由于笔者道行不够(菜的抠脚),就不阐述源码了。

现在就剩下autolease了:

autorelease看上去好像ARC,其实并不。autorelease就像c语言的作用域一样,当c语言的自动变量超出作用域时将会被废弃,使用autorelease时,当Objc的对象超出其作用域时,其release实例方法将会被调用。

autorelease的具体使用方法如下:

(1)、生成并持有NSAutorelease对象;NSAutoreleasePool = [[NSAutoreleasePool alloc] init];

(2)、创建对象;  id obj = [[NSObject alloc] init];

(3)、调用已分配对象的autorelease实例方法;[obj autorelease];

(4)、废弃NSAutorelease对象;[pool drain];

对于所有调用过autorelease实例方法的对象,在废弃NSAutoPool对象时([pool drain];);都将调用release方法;对象的生命周期就处于NSAutoreleasePool = [[NSAutoreleasePool alloc] init]与[pool drain]之间;及时的废弃NSAutorelease对象可以有效的避免内存不足的现象。

我们在使用autorelease的时候,不一定要使用NSAutorelease对象,因为程序主循环的NSRunLoop,对NSAutoreleasePool对象进行了生成、持有、和废弃的处理,NSRunLoop不在本文的讨论范围之内,以后的博客将会详细介绍。

严肃了那么久,(装逼)好累,一直承受着我这个年纪不该有的帅气和智商,唉|我好累!!!
















1 0
原创粉丝点击