OC采用了引用计数(retain count)对对象内存进行管理,例如,某个对象alloc了,那么这个对象的引用计数就加1,retain时加1,当对象不需要用时就需要销毁对象,释放内存,需要对象调用release方法,release会让引用计数减1,只有引用计数消失,相当于等于0,对象才会调用dealloc真正销毁这个对象。
每个OC对象都有自己的引用计数器,是一个整数表示对象被引用的次数,即现在有多少东西在使用这个对象。对象刚被创建时,默认计数器值为1,当计数器的值变为0时,则对象销毁。
ARC是xcode5中引入的自动引用计数,其原理与MRC是一样,只是系统帮助我们添加了retain和release。
苹果官方对于ARC机制中对象的内存引用规则:
(1)任何对象,如果仍有持有者,就不会销毁
(2)任何对象,已经没有任何持有者,即自动销毁
持有者就是指向对象的指针,如果是strong修饰的,即是对象的持有者,如果是weak属性的,则不是持有者
现实中的许多旧的项目,还有一些比较老的第三方库,可能都是采用MRC环境编写的,我们在对其进行扩展或者做新项目的兼容的时候,可以在xcode中对其进行混编。
选择:target->build phases->compile sources
如果工程是ARC,要混编MRC的文件,我们选中compiler flags,后面设置为-fno-objc-arc
如果工程是MRC,要混编ARC文件,我们在后面设置-fobjc-arc
MRC模式下,所有的对象都需要手动的添加retain、release代码来管理内存,必须遵守谁创建,谁回收的原则。引用计数为0的时候,必须回收,如果没有回收,会造成内存泄露,如果继续释放,会造成野指针。引用计数不为0,不能回收。release后的对象,虽然已经释放,但是它的指针地址仍然存在,只是指向了一块已经释放且无用的内存,所以我们建议release后直接赋个nil来置空。
ARC(自动引用计数),可以自动的管理内存。在ARC模式下,只要没有强指针(强引用)指向对象,对象就会被释放。在ARC模式下,不允许使用retain、release、retainCount等方法。并且,如果使用dealloc方法时,不允许调用[super dealloc]方法。ARC**模式下的property变量修饰词为strong、weak,相当于MRC模式下的retain、assign。strong :代替retain,缺省关键词,代表强引用。weak:代替assign,声明了一个可以自动设置nil的弱引用,但是比assign多一个功能,指针指向的地址被释放之后,指针本身也会自动被释放。
ARC机制的使用规则
(1)不能使用NSAllocateObjec或NSDeallocateObject函数来创建对象
(2)不能在C语言的结构体中使用对象指针,同时建议用object-c的类来管理数据而不是结构体
(3)不得使用NSAutoreleasePool对象。ARC中,全部使用@autorelease关键字代替,且比NSAutoreleasePool更高效
(4)不得使用内存Zone,那些牵涉NSZone的方法都不得使用。
(5)不得对一个属性变量的取值方法命名以new开头
(6)outlet均用weak关键字修饰,除非他是xib中最顶部的界面元素,则需要strong。
(7)Core Foundation不适合ARC,该创建的仍创建,该释放的仍释放。
其中关于自动释放池:
当向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
Objective-C是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
NSAutoreleasePool(MRC)和@autorelease(ARC)就是用来做引用计数的管理工作的,这个东西一般不用你管的. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一。