ARC全称为自动引用计数(automatic referencecounting,ARC)。这是苹果公司最近的内存解决机制,它将在程序编译时自动在合适的位置添加retain和release语句,来进行内存的释放回收。
ARC在以前版本中是可选的功能,但是在最近的版本中,苹果公司将ARC列为了默认的选项。
ARC不是万能的,ARC是有局限性的,即ARC只对可保留的对象指针(ROPs)有效,通俗点说,就是对强指针有效,什么是强指针呢?前面说@property的时候涉及到了,但是没有说明。
强指针:默认情况下所有的指针都是强指针,声明强指针__strong。
弱指针:声明弱指针__weak,当弱指针指向的对象不存在,则直接清空弱指针。
官方的定义一下可保留的对象指针:
1>代码块指针
2>Objective-C对象指针
3>通过__attribute__((NSObject))类型定义的指针
好吧,说实话上面的可保留的对象指针我是没看明白,所以暂时就先记住ARC对强指针有效就好啦。
ARC的作用规则:只要没有强指针指向的对象就会立即释放。
比如说:一个对象A,现在有个强指针p 指向了对象A,同时呢又有一个弱指针 q 指向了A,当 p 指针不存在或者为 0 的时候,即 p 指针不再指向A,这个时候对象 A没有强指针被指向,只有一个弱指针 q 指向,那么ARC就会自动释放对象A,对象A就不存在了,对象A都不存在了,那么弱指针 q找不到所指向的对象,于是弱指针q也就变成了 0 。
看到这里会有疑惑,为什么要有弱指针,存在即合理,弱指针是要对循环引用负责的。
当存在类B 和类 C ,类 B 的成员变量中含有类 C 类型的成员变量,类 C 的成员变量中含有类 B类型的成员变量,声明一个指针 p (这里没有做特殊说明,所有的指针均为强指针)指向一个新创建的属于类 B 的对象 B,同时声明一个指针 q 指向一个新创建的属于类 C 的对象 C ,这个时候将指针 p 的地址赋给对象 C 的属性中的类 B类型,则对象 C 包含了对象 B ,再将指针 q的地址赋给对象 B 的属性中的类 C 类型,则对象 B 包含了对象 C 。这个时候,当程序运行结束时,由于对象 B 强指向了对象 C,对象C也强指向了对象 B ,两个对象均不会释放。
上面说的有点绕,我自己都快看哭了,代码说一下。
#import
@ClassDog
@interfacePerson : NSObject
@property(nonatomic, strong) Dog *dog; // 人养狗
@end
#import
@ClassPerson
@interfaceDog : NSObject
@property(nonatomic, strong) Person *person; // 狗的主人
@end
intmain ()
{
Preson*p = [[Person alloc] init];
Dog*d = [[Dog alloc] init];
p.dog= d;
d.person= p;
return0;
}
这个时候,p.dog指向了d,d.perdon指向了p(当然这么说肯定不对,我只是用指针代指来对象)。两个对象都有强指针指向,所以都不会释放,这个时候就需要用到了弱指针,将其中一个类的成员变量@property属性声明为weak,这样当结束时,有一个对象因为没有强指针指向,所以就被释放,另一个对象也就失去了强指针的指向,也就被释放掉了。
由此可以看出,循环引用必须使用弱指针,这样才能保证内存释放的完整性,因为现在的程序基本上ARC都能完美的支持了,而且绝大部分都是由ARC来管理内存的,所以对于非ARC和ARC的转换,还有对于一部分文件不使用ARC的设置,对于只允许一部分文件使用ARC的设置我就不说啦,可以理解为,我根本都没看,嘿嘿。
附加:以前的内存管理中是需要讲释放内存的代码手动写进去的,释放内存需要调用dealloc方法,这个方法是允许被重写的,但是重写的时候不允许调用调用父类该方法,即不允许[superdealloc];