内存管理
介绍
管理内存的常见方式
1.垃圾回收:java常见的管理内存的方式,系统来检测对象是否被使用,是否被释放
2.MRC手动管理引用计数,iOS管理内存的方式,程序员通过手动的方式来管理对象是否被释放
3.ARC自动管理引用计数,基于MRC,系统自动的管理内存,以后我们还是先使用MRC,培养管理内存的习惯
内存常见问题
- 内存溢出
- 野指针异常
iOS的内存管理
- ARC
- MRC
其中,MRC的内存管理机制是引用计数
内存管理机制
OC采用引用计数的机制,即一个新的引用指向对象的时候,引用计数器(retainCount)就递增,当释放掉一个引用的时候,计数器就递减.到0的时候调用dealloc,即释放占有的资源
影响引用计数的方法
+alloc
// 对象被创建出来之后,他的引用计数retainCount就变成1
Boy *boy = [[Boy alloc] init];
NSLog(@"%ld",boy.retainCount);
结果:
2015-07-28 18:45:45.361 OC08,09_内存管理[2694:166290] 1
-retain
// retain:对对象的引用计数进行+1的操作
[boy retain];
[boy retain];
[boy retain];
NSLog(@"%ld",boy.retainCount);
结果:
2015-07-28 18:45:45.361 OC08,09_内存管理[2694:166290] 4
-release
[boy release];
NSLog(@"%ld",boy.retainCount);
[boy release];
[boy release];
[boy release];
结果:
(最后是因为在类中声明了dealloc)
2015-07-28 19:04:21.023 OC08,09_内存管理[2721:171301] 3
2015-07-28 19:04:21.024 OC08,09_内存管理[2721:171301] 对象被释放
注意:当对象的引用计数1 -> 0的时候,会自动调用dealloc方法.dealloc才是对应对象释放的方法,并且注意,如果多次对对象进行release释放,会造成过度释放,过度释放也是最常见的内存问题.
当对象调用release的时候,它的引用计数是1,这个对象就不在对它的引用计数进行 -1 操作,而是直接调用dealloc方法,所以,在访问对象的引用计数的时候还是1
-autorelease
Boy *boy = [[Boy alloc] init];
[boy retain];
[boy retain];
NSLog(@"%ld",boy.retainCount);
// release马上会把对象的引用计数-1,但是autorelease会延迟对对象的计数-1
// 自动释放池
// 只要对象用autorelease释放,会把对象放入到系统的自动释放池中,等出了池子的范围,对象引用计数自动-1,这个相当于java的垃圾回收,对象释放由系统来管理
@autoreleasepool {
[boy autorelease];
NSLog(@"%ld",boy.retainCount);
}
NSLog(@"%ld",boy.retainCount);
-copy
copy也可以改变引用计数,但是他改变的是新对象的引用计数,而原先的对象计数不变
NSArray *arr = @[@"1",@"2",@"3",@"4"];
NSLog(@"%ld",arr.retainCount);
NSArray *newArr = [arr copy];
NSLog(@"%ld",newArr.retainCount);
结果:
2015-07-28 19:35:46.831 OC08,09_内存管理[3016:189709] 1
2015-07-28 19:35:46.832 OC08,09_内存管理[3016:189709] 2
内存管理的原则
凡是使用了alloc、retain或者copy让内存的引用计数增加了,就需要使用release或者autorelease让内存的引用计数减少。在一段代码内,增加和减少的次数要相等。
注意:便利构造器在返回对象的时候会加上一个autorelease,所以用便利构造器创建的对象不需要对内存进行内存管理
copy
跟retain不同,一个对象想要copy,生成自己的副本,需要实现 NSCopying协议,定义copy的细节(如何copy)。如果类没有接受NSCopying协议而给对象发送copy消息,会引起crash。
copy方法的实现
Boy.m
- (id)copyWithZone:(NSZone *)zone
{
Boy *b = [Boy allocWithZone:zone];
b.hobby = _hobby;
b.name = _name;
return b;
}
版权声明:本文为博主原创文章,转载请注明原文地址