一、引用计数器
每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,每个OC对象内部有4个字节的存储空间存储引用计数器
1、作用
- 当使用alloc、new、copy创建一个新对象时,引用计数器的默认值为1
- 当一个对象的引用计数器的值为0时,对象占用的内存就会被系统回收
- 判断对象占用内存是否回收的唯一依据
2基本使用
1> retain :计数器+1,会返回对象本身
2> release :计数器-1,没有返回值,不代表释放对象
3> retainCount :获取当前的计数器
3、 内存回收
- 当一个对象的引用计数器的值为0时,它将会被销毁,对象占用的内存被系统回收
- 当一个对象被回收的时候,系统就会自动调用dealloc方法
- 一般重写dealloc方法,释放相关资源
- 重写dealloc方法,一定要调用[super dealloc],这句调用要放在最后面
- 对象被回收,占用的内存就不可再用,否则会导致野指针错误
4、相关概念
僵尸对象 :所占用内存已经被回收的对象,僵尸对象不能再使用
野指针 :指向僵尸对象(不可用内存)的指针,给野指针发送消息会报错(EXC_BAD_ACCESS)
空指针 :没有指向任何东西的指针(存储的东西是nil、NULL、0),给空指针发送消息不会 报错
5、重写dealloc方法简单示例
- (void)dealloc
{
NSLog(@"Person对象被回收");
[super dealloc];
}
二、内存管理原则
1、谁创建,谁release
如果你通过alloc、new、 copy来创建一个对象,那么你必须调用release或autorelease,
换句话说,不是你创建的,就不用你去[auto]release
2、谁retain,谁release
只要你调用了retain,无论这个对象是如何生成的,你都要调用release
三、内存管理代码规范
1、原则
只要调用了alloc,必须有release(autorelease),对象不是通过alloc产生的,就不需要release
2、set方法的代码规范
(1) 基本数据类型
- (void)setAge:(int)age
{
_age = age;
}
(2) OC对象类型
- (void)setCar:(Car *)car
{
// 1.先判断是不是新传进来对象
if ( car != _car )
{
// 2.对旧对象做一次release
[_car release];
// 3.对新对象做一次retain
_car = [car retain];
}
}
3、dealloc方法的代码规范
1> 一定要[super dealloc],而且放到最后面
2> 对self(当前)所拥有的其他对象做一次release
- (void)dealloc
{
[_car release];
[super dealloc];
}
四、@property参数
1、使用@property参数原因
@property可以生产set、get方法,但是生产的set方法仅仅是赋值,并没有进行内存管理
示例:
@property Book *book;
- (void)setBook:(Book *)book
{
_book = book; //仅是赋值操作
}
2、set方法内存管理相关的参数
- retain : release旧值,retain新值(适用于OC对象类型)
- assign : 直接赋值(默认,适用于非OC对象类型)
- copy : release旧值,copy新值
示例:
@property (retain) Book *book;
生成的set方法里面,release旧值,retain新值
- (void)setBook:(Book *)book
{
if (_book != book)
{
[_book release];
_book = [book retain];
}
}
3.是否要生成set方法
readwrite : 同时生成setter和getter的声明、实现(默认)
readonly : 只会生成getter的声明、实现
4.多线程管理
nonatomic : 性能高 (一般就用这个)
atomic : 性能低(默认)
示例:
@property (nonatomic, assign) int age;
5.setter和getter方法的名称
setter : 决定了set方法的名称,一定要有个冒号 :
getter : 决定了get方法的名称(一般用在BOOL类型)
示例:
@property (getter = isRich) BOOL rich;
//使用
Person *p = [[Person alloc] init];
p.rich = YES;
BOOL b = p.isRich;