ARC跟非ARC的本质区别是:ARC下当增加一个强指针指向一个对象的时候,计数自动加1,非ARC下不会自动增加
每个对象中都有一个引用计数器(4个字节),用来表示当前变量的引用计数
[a retainCount]:获取a对象的引用计数器的数值
[a release]:对象的引用计数减1,如果计数是1时,再给对象发送release就会释放对象(释放的时候是不是判断引用计数器为1,如果再发送release消息就释放,而不是判断引用计数器为0的时候释放?)
[a retain]:对象的引用计数加1,同时返回对象本身(self)
[a copy]: 产生一个新对象,内容跟旧对象一样
NSString的retain和copy是一样的,返回的都是对象本身
只有三种:retain,alloc,copy可以引起计数加1
给一个对象指针发送完release消息后,最好给其赋值为nil.
给nil指针发送任何消息都不会报错
如果一个对象指针已经被释放,还强行给其发送消息,一般不会报错,但是很危险,因为它所指向的地址已经不再被该指针合法拥有
dealloc方法:对象被回收 之前会自动调用,重写必须调用[super dealloc](一般最后一行)
非ARC下内存管理原则:
1.只要调用了alloc,retain,copy,则必须release(谁alloc,retain,copy,谁release)
(不是通过这三种方法产生的,不要release)
僵尸对象:
所占用的内存已经被回收,且不能再被使用
野指针:·
指向僵尸对象的指针,特点是给野指针发送消息会报错
空指针:
没有指向任何地址的指针,比如nil,NULL,0;
retain用在属性里面,表示release旧值,retain新值
@property (retain)NSString *name;
copy用在属性里面,表示release旧值,copy新值(产生一个新的对象,不是所有的对象都可以copy,要实现协议)
2、retain点语法
OC内存管理正常情况要使用大量的retain和release操作;
点语言可以减少使用retain和release的操作。
编译器对于retain展开形式:
@property (retain)Dog *dog;
展开为:-(void) setDog:(Dog *)aDog;
-(Dog *)dog;
@synthesize dog = _dog; //(retain属性)
展开为:-(void) setDog:(Dog *)aDog{
if(_dog != aDog){
[_dog release];
_dog = [aDog retain];
}
};
-(Dog *)dog{
return _dog;
};
------------------------------------------------------------------------------------------------------------
ARC环境下不会出现僵尸对象和野指针
ARC下:只要没有强指针指向一个对象,对象就被释放
默认情况下,所有的指针都是强指针: 修饰局部变量(weak,unsafe_unretained也是): __strong(如果是属性的话 不用加__ 直接strong)
弱指针:__weak(set方法直接赋值),弱指针指向的对象只要被释放,则弱指针会自动被赋值为nil(assign也是直接赋值,但是指向的对象被释放后,成为野指针,不会置成nil)
unsafe_unretained跟assign差不多,基本类型一般用assign,对象类型一般用unsafe_unretained
[[A alloc]init]; 产生对象,不接收这个对象的话,在ARC下相当于
A *a = [[A alloc]init];
a=nil;
NSLog(@“xxxx%d”,[[A allo]init].age); 尽量不要这样用,在非ARC下会有严重错误,内存泄露. 在ARC下,可能还没被使用就释放了
非ARC下成员变量是对象的话,一般用retain修饰,在ARC下用强指针(strong)修饰