1.ARC:Automatic Reference Counting(自动引用计数器)
是iOS自5.0版本之后增加的新特性,会自动生成release,retain等语句,消除了手动管理内存写代码的繁琐和麻烦,ARC机制是编译器特性 ,不是运行时特性,也不是垃圾回收
2.ARC的基本原理(判断准则):只要没有强指针指向对象,就会释放对象
指针分两种:强指针,默认情况下,所有的指针都是强指针__strong
弱指针,__weak
3. ARC特点:
(1)不允许调用release、retain、retainCount。
(2)允许重写dealloc,但是不允许调用[super dealloc];
(3)@property的参数
strong:成员变量是强指针,相当于以前retain(使用OC对象)
weak:成员变量是弱指针,相当于以前assign(使用OC对象)
assign:基本数据类型,直接赋值。(适用于非OC对象)
(4)以前的retain,改为用strong,其余不变
如: 以前(手动管理内存时)@property (nonatomic,retain) Car *car;
现ARC机制中改为:@property (nonatomic,strong) Car *car;
错误写法(没有意义的写法)
__weakPerson *p = [[Personalloc]init]; 这句代码是创建了一个Person对象,创建完后因为没有强指针指向它,所以刚一创建就被释放了。
注意:弱指针指向的对象被回收后,弱指针会自动变为空指针(nil指针),不会引发野指针错误.
分析1:
int main()
{
Person *p = [[Person alloc] init];
Person *p2 = p;
p = [[Person alloc] init]; //这两个Person对象在函数结束后才被释放
}
分析:第一行代码结束后创建的对象由指针p指向它,第二行代码过后指针p2也指向它,第三行代码过后,指针p指向另一个Person对象,这两个对象都是在函数结束后才被回收的,函数结束后,指针p和p2这两个局部变量被回收,此时,内存中的两个Person对象因为没有强指针指向他们,所以也被释放。
分析2:
如果在上述代码中最后一行加上 p2 =nil;那么此时第一个Person对象在p2 = nil;这行代码过后就被释放了,因为p2 =nil是把指针p2清空了,此时指针p2就不再指向第一个Person对象了,既然没有强指针指向它,那么他就被释放了。
分析3:
int main()
{
Person *p = [[Person alloc] init];
__weak Person *p2 = p;
p = nil;// 第一行创建的对象在这一行过后被释放
p2 = nil;
}
第一行代码过后,指针p指向Person对象,第二行代码过后,弱指针p2指向Person对象,此时指针p和弱指针p2都指向这个Person对象,三四行代码是分别清空了指针p和p2,在第三行代码过后,只有弱指针p2指向这个对象,所以此时对象被释放。因此对象实在第三行过后被释放的,并不是第四行。
分析4:在Person对象中声明Dog时,是strong类型的。@property (nonatomic,strong) Dog *dog;
int main()
{
Dog *d = [[Dog alloc] init];
Person *p = [[Person alloc] init];
p.dog = d;
d = nil; //Dog对象不会被释放,因为还有Person对象中的_dog指向它
}
分析:前三行代码过后内存中情况如下图
第四行代码过后,指针d被清空,但是Person对象中的_dog还在指向Dog对象,所以说Dog对象不会被释放.
如果在最后加上 p = nil; 指针p被清空,那么此时Person对象就没有强指针指向它了,所以Person对象被释放,Person对象一被释放,Dog对象也没有指针指向,所以他也就被释放
如果是@property (nonatomic,weak) Dog *dog;那么,第一种情况下d= nil过后,Dog对象就被释放了,因为没有强指针指向它了。
ARC的转换功能:
如果想把非ARC转换为ARC的,那么在xcode菜单栏中的edit下的refactor中找到covert to Objective-C ARC ,选择项目进行转换即可。
如果想要某些文件是非ARC的,那么在xcode6.0.1中如下图找到编译文件,双击这个文件就会出现一个对话框,在里边写上-fno-objc-arc,即可
如果项目环境本来就不是ARC的,这是我们想让某些文件是ARC的那么在刚才的框里写-f-objc-abc就可以了。
ARC的循环引用
int main()
{
Dog *d = [[Dog alloc] init];
Person *p = [[Person alloc] init];
p.dog = d;
d.person = p;
}
两个都是强指针,所以没办法被释放,
解决方法: 一端用strong,一端用weak