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 ) { [ _car release]; _car = [ car retain]; } }
3)dealloc方法
a. 对self所持有的属性release一次
b. [super dealloc]放在最后
- (void) dealloc { [car release]; [super dealloc]; }
4)不要出现以下垃圾代码
stu.car = [[Car alloc] init]; //会使引用计数为2 [[Car alloc] init].speed = 100; //无法释放了
@property的内存管理参数
@property应有且仅有一个内存管理参数。
MRC下,内存管理参数包括:assign retain copy,默认为assign
这些内存管理参数,能够决定属性setter方法的实现
assign:setter不修改引用计数
@property (nonatomic,assign) NSInteger age;
setter方法:
- (void)setAge:(NSInteger)age { _age = age; }
retain:修改该属性的引用计数(按照代码规范)
@property (nonatomic, retain) NSNumber * age;
setter方法:
- (void)setAge:(NSNumber *)age { if ( _age != age ) { [_age release]; _age = [age retain]; } }
copy:深拷贝赋值,一般用于NSString
@property (nonatomic, copy) NSString * name;
setter方法:
- (void)setName:(NSString *)name { if ( _name != nil ) { [_name release]; } _name = [name copy]; }
对象复合关系出现的循环引用问题
问题描述:
一个Person对象,一个Card对象,互为属性
如果一个内存参数均为retain,则应会使引用计数均为2
这样做对任意对象release,都不会使对象销毁
解决方法:
一端使用retain,一端使用assign