Objective-C内存管理

管理范畴:OC对象

每个计算机系统可供程序使用的内存资源是有限的。我们要关心两件事情:

在需要时分配,用完之后释放

不要使用任何已被释放的内存资源,否则将无用陈旧的值导致各种各样的错误发生

三种管理方式:

手动管理方式 MRC(Manual referencing count)

半自动管理方式 autoreleasepool

自动管理方式 ARC(Auto referencing count)


引用计数与内存管理准则

Cocoa采用了一种称为“引用计数”的技术,它为每个对象关联一个整数:

相关方法:

-(instancetype)retain//引用计数+1-(void)release//引用计数-1-(NSUInteger)retainCount//对象的当前引用计数值

使用引用计数:

a.当创建一个对象时(alloc new copy),被创建对象的引用计数为1

b.当某段代码要访问这个对象时就对该引用计数+1 (retain)

c.当这段代码完成后要对这个引用计数-1 (release)

d.当引用计数为0时,表示没有代码访问这个对象了,该对象就会被销毁

(销毁前自动向其发送一个dealloc消息)。


场景解释:游戏中的房间、副本等


内存管理的准则:

1)内存管理的原则:

只要还有人在使用某个对象,那么这个对象就不会被回收;

只要你想使用这个对象,那么就应该让这个对象的引用计数器+1;

当你不想使用这个对象时,应该让对象的引用计数器-1;

2)谁创建,谁release

a.如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法

b.不是你创建的就不用你去负责

3)谁retain,谁release

总结:有始有终,有加有减。


MRC中的代码规范

1)只要调用了alloc,就必须有release

2)属性的setter方法

a. 基本数据类型直接赋值

-(void)setAge:(int)age{_age=age;}


b. OC对象,先判断和属性旧值的是不是同一对象

如果是,则什么也不做;如果不是,将旧值release,并对新值retain

-(void)setCar:(Car*)car{if(car!=_car){[_carrelease];_car=[carretain];}}


3)dealloc方法

a. 对self所持有的属性release一次

b. [super dealloc]放在最后

-(void)dealloc{[carrelease];[superdealloc];}


4)不要出现以下垃圾代码

stu.car=[[Caralloc]init];//会使引用计数为2[[Caralloc]init].speed=100;//无法释放了


@property的内存管理参数

@property应有且仅有一个内存管理参数。

MRC下,内存管理参数包括:assign retain copy,默认为assign

这些内存管理参数,能够决定属性setter方法的实现

assign:setter不修改引用计数

@property(nonatomic,assign)NSIntegerage;

setter方法:

-(void)setAge:(NSInteger)age{_age=age;}

retain:修改该属性的引用计数(按照代码规范)

@property(nonatomic,retain)NSNumber*age;

setter方法:

-(void)setAge:(NSNumber*)age{if(_age!=age){[_agerelease];_age=[ageretain];}}


copy:深拷贝赋值,一般用于NSString

@property(nonatomic,copy)NSString*name;

setter方法:

-(void)setName:(NSString*)name{if(_name!=nil){[_namerelease];}_name=[namecopy];}

对象复合关系出现的循环引用问题

问题描述:

一个Person对象,一个Card对象,互为属性

如果一个内存参数均为retain,则应会使引用计数均为2

这样做对任意对象release,都不会使对象销毁

解决方法:

一端使用retain,一端使用assign