前言:本猿做了将近5年的ios开发,之前用了三年的手动释放(MRC)来开发应用,正当自己觉得自己对ios内存管理用的炉火纯青的时候,苹果推出了ARC, 一开始可能和大多数猿类一样,对其嗤之以鼻。认为它不如手动释放效率高。后来经过一段时间,大家开始慢慢深入的认识了ARC后,开始意识到他的好处。用ARC开发出来的应用的稳定性非MRC所能比拟。于是没法办,开始随波逐流,匆匆的开始使用起了ARC,从大多数论坛上看到大家对ARC的认识就是:苹果在编译的时候会自动帮你加上release....。哦,原来这么简单,原来就是在MRC的基础上,编译器自己帮你加上release,原来需要release的地方,就不需要写了。两年多来,我就是抱着这样的理解用着ARC,直到今天以前!这两天闲着没事,重新研究了一些代码,发现按照之前的思路,有些内存问题根本解释不通,如是抓紧又看了几篇关于ARC的文章,并写了一些测试代码,才恍然大悟,原来很多网友和我之前对ARC的理解大错特错了。于是,写一下内容重新梳理一下对ARC和MRC的认识...
手动释放MRC
苹果的MRC使用的是内存计数器的方式管理,本人觉得用一个比喻来理解非常恰当,在MRC中内存就像一条狗,开发者这就是条狗的主人,每次作计数加1的操作就相当于给狗多栓了一根绳子,每次作计数器减1操作就相当于给狗解掉一根绳子,当所有绳子都解开的时候,狗就跑了,内存就被系统回收了。
- alloc,new,copy:系统会返回一块计数器为1的新内存,相当于卖狗的人给了你一条已经栓好一根绳子的狗
- retain:会对内存的计数器加1,相当于给狗加一条绳子
- release:会对内存计数器减1,相当于给狗解一条绳子
- autorelease:会在某该函数栈结束后对该内存计数器减1,相当于给狗狗解开了绳子,但是狗狗现在还在吃食,你不用管它了,它吃完食后发现绳子没了会自动跑开的。
自动释放ARC
之前我认为ARC就是从MRC加了一个智能点编译器,现在我觉得ARC的思想和MRC的思想完全是不同的,学习ARC的时候如果完全忘记MRC会更好理解。MRC是以开发者为核心,而ARC是以内存为核心。我们用氢气球来比喻ARC下的内存,ARC下的内存就象底下栓着一根线的很大氢气球,气球下面有两种人,一种是有手的正常人,他们会用手拉着气球,也有很多人没有手的残疾人,他们只能围观着气球。但是只要有一个人拉着它,气球就不会飞走。否则气球就会飞走,气球飞走了,那些围观的人就都会散了。
- ARC下的指针是有类型的,分为strong,weak两种类型的指针。这点MRC下并没有,MRC下指针没有类型之分。
- alloc,new,copy:在ARC中这三个操作,就相当于从卖气球人手里买来一个气球,但这是你必须找一个有手的人来拉着这个气球,否则买来就飞走了。
- strong:strong类型的指针就是那种有手的人,将一个strong类型的指针指向一块的内存的时候,他就会拉着它。
*weak:weak类型的指针就是没有手的人,他们指向一块内存的时候,只会看着它,并不能拉住他。 - 重点是编译器并不会给你作什么release操作,因为arc里根本没有release这东西。在ARC里面系统只做了这三件事
1.在变量作用域结束时,将变量置为nil
2.在一块内存没有strong类型指针指向的时候,释放内存,并将所有指向这快内存的weak指针置nil
3.一个指针默认声明出来是strong类型
举个例子
- (void) test
{
//array1,array2默认是strong类型指针
NSArray *array1;
NSArray *array2;
//weak1,weak2是weak类型指针
NSArray *__weak weak1;
NSArray *__weak weak2;
//系统申请了@"aaa",@"bbb"两块内存分别交给有手(strong)的array1和array2
array1 = [[NSArray alloc] initWithObjects:@"aaa", nil];
array2 = [[NSArray alloc] initWithObjects:@"bbb", nil];
//没有手的(weak)weak1,weak2分别看向@"aaa",@"bbb"两个气球
weak1 = array1;
weak2 = array2;
//array1放弃了@"aaa",转而拉住了@"bbb"
array1 = array2;
//现在只剩下weak1看着@"aaa", 但没有人拉住@"aaa",所以@"aaa"被系统释放了,weak1被置nil了
NSLog(@"%@", weak1); //输出null
//而@"bbb"现在还有两个人拉着,所有内存还在,那么@"bbb"什么时候会释放呢?
NSLog(@"%@", weak2); //输出@"bbb"`
//整理array1,array2的作用域结束了,被系统制为nil。@"bbb也就释放了"
//array1 = nil;
//array2 = nil;
}