首先我们要知道的是,MRC在ARC之前。
MRC全称是ManualReference Counting,也有人称为Manual Retain Release(MRR)。简单来说就是传统的手工的内存管理方法,内存的分配和回收任务全部落在程序员身上。
而ARC的全称是AutomaticReference Counting,意思为自动内存管理方法。
把程序员要生于逢时来形容MRC和ARC的变化,可以说最为贴切。在IOS 5和Xcode 4.2以前,ARC还没有出现,那时候使用Oc的程序员在编写代码的时候还必须考虑内存管理的问题,并且要在代码中加入retain , release , dealloc 等语句来管理内存,而且必须小心谨慎,不然就会出现内存泄漏和无效指针,甚至导致程序的崩溃。几乎每一个alloc,retain,copy都会有release与之对应,如果有上万行代码,工作量可想而知。
在MRC中,存在以下标识符
内存管理,顾名思义就是管理自己创建的涉及内存的指针,对象。当你新建一个对象,完成了对它的使用,你就要自行把它的内存释放出来,否则就造成了内存的泄漏(memory leak)。当你新建一个指针,所记录的地址的对象已经被释放,那么这就是一个无效的指针(dangling pointer),这同样增加了程序的不稳定性。
所以在MRC中,存在着如此的对象管理规则,每一个对象被创建以后,都会有一个Reference Count,初始化为1。当你使用完了之后,就要release掉它,使它的Reference Count减1,当一个对象的Reference Count为0,那么系统就会把它的内存释放掉。
在上面表格中的标识符中,retain使Reference Count加1,release使Reference Count减1.
注:由于MRC以成为过去,现在Xcode的项目都默认使用ARC内存管理机制,所以先要测试MRC,必须把项目设置为MRC。
方法如下:
在项目的Build Settings 下找到automatic reference counting,把目标设置成NO,也就是禁用ARC
我们来看一个例子:
可能你会认为上面的代码没有错误,而且当你运行程序后,编译器也不会报错。但事实是,我们使用alloc创建一个指针,最后却没有去释放它,这存在着明显的内存泄漏问题。
shift+command+B,编译器提出一个内存管理问题。
在代码的最后一句,编译器提示我们没有把str指针内存释放掉。
那么我们需要如何修改呢,简单,只需把str内存人为释放掉就行了。
但很多情况下,你创建出来的对象,不一定只有你使用,还有项目其他的程序员也会用到。如果你真在使用其他人的对象,但是其他人不知道用完该对象之后就把它给释放掉了,那就造成了你使用了一个不存在的对象,结果可想而知。
所以说,当我们要使用其他的对象的时候,我们要告诉拥有者,我们正在使用它。
例子:
//MRCclass
//main.m
可以看出在输出myMRC对象内存储的信息之前,已经把myMRC里面含有的信息release掉了,所以导致了myMRC最终含有的是一个空指针。
修改myMRC.m的代码为
意思是在我使用array之前,先retain使array对象的Reference Count的计数加1,(本例子)使对象的Reference Count变为2,以至于就算拥有者release掉该对象,Reference Count减1,Reference Count还没有为0,编译器并不会把array对象的内存释放掉。
标识符copy具有相同的作用,不过copy是深度复制一个新的对象,所以copy之后,array的Reference Count仍然是1,只不过,就算array被release掉,也不会影响到myMRC,因为myMRC变量指向的不再是array。
然而现在绝大多数情况下,我们都在使用ARC的内存管理机制,原因无它,方便!
在我们的pc机中,也存在着内存的管理机制问题,不过并不是MRC或者ARC,而是GC(Garbage Collector),GC是根据我们程序运行时,系统自行分析该对象是否还在使用,不就释放内存空间。这种内存管理机制对程序猿来说简单,而且准确,不会平白无故把一个正在使用的对象的内存释放掉。当时遗憾的是GC的优点是要消耗大量的内存,在pc机中,内存大多数情况下不存在内存的问题。但是在移动产品中,内存是有限的,尽量地减少内存的浪费是非常必要的。所以,使用GC是不现实的。
而ARC其实本质上就是MRC,只不过内存的管理,也就是retain,release,autorelease不再是程序员来编写,而是编译器自动检查,自行在代码中插入,这样就大大地减少了程序员对内存的管理,甚至没有。
当然,一个新的机制(ARC下)就带来了新的规则:
1。代码没有retain,autorelease,retainCount。
2.虽然我们可以自行定义dealloc方法(类似C的析构函数),但是我们不能在写[super dealloc](也就是不能调用父类的析构函数)
3。不能使用struct。
4.加入了一些新的标识符,来描述一个变量,对象的引用程度,如strong,weak。
5.不再有NSAutoReleasePool,而是使用@autoreleasepool{},在main函数里面我们可以看到。
最后:
在类property中,可以加入修饰词,在MRC中有(nonatomic \ atomic)(retain \ assign \ copy) (readonly \ readwrite) 。
注:nonatomic与多线程有关,默认为atomic,也就是使用多线程锁
retain 代表强引用,assign代表弱引用
在ARC中,新加入了一些修饰词 (strong \ weak)
普通的成员可以用修饰词:(_strong \ _weak) (_unsafe_unretained \ _autoreleasing )
注:strong代表强引用,weak代表弱引用。