oc 第五天(内存管理)
OC的重点: 内存管理
1 基本原理
1手动内存回收
alloc 让计数器从 0 变 1;
retain 计数器 +1;
copy 新开辟一块内存,把原对象的值复制;
release 计数器 -1;
autorelease 计数器延迟-1;
alloc 不再解释
retain :先看下面这段程序
Person *p = [[Person alloc]initWithName:@"fds" age:12 sex:@"cfds"]; [p retain]; [p release]; [p release];首先 alloc 计数器+1 = 1,retain一次,计数器再+1 = 2 ,release二次 -2 计数器 = 0 系统调用delloc
这样 这个对象才会正确的被释放掉
retain 又会牵扯到另一个问题,属性在Student类中定义了一个
@property (retain)Book *book;
- (void)setBook:(NSString *)book { if (_book != book) { [_book release]; _book = [book retain]; } } - (NSString *)book { return [[_book retain] autorelease]; }这是系统在定义book属性后默认给我们写的setter 和 getter的代码 ,首先看setter
当第一次为book赋值的时候
[_book release];
由于_book为空 OC中对于一个为nil(null)的对象,它调用的任何方法都是无效的,所以执行
_book = [book retain];那么book的计数器为 2 这样的话 在外面创建book对象时 release一次 然后 当下一次赋值的时候
会把_book首先release一次 这样就会把本次的book释放掉,而且也符合谁使用,谁回收的原则,这样
也会产生一个问题,当Student释放时,最后一次的_book怎么释放
if 的作用是为了防止第二次赋值同一个值
这就牵扯到 delloc方法:
delloc方法,是当计数器为0的时候系统自动调用的,不会手动调用,一般都会改写这个方法,把本类中定义
过的所有对象类型的属性都release 一次,那么当student对象被回收时,所有调用的内存都被回收了.
copy:
copy的使用也要牵扯到属性这个问题,
@property (copy)Book *book;
copy首先要实现NSCopy接口 实现里面的
- (id)copyWithZone:(NSZone *)zone方法 下面是一个Person类的例子
- (id)copyWithZone:(NSZone *)zone { Person *newPerson = [Person allocWithZone:zone]; [newPerson setAge:[self age]]; [newPerson setName:[self name]]; [newPerson setSex:[self sex]]; return newPerson; }这样就实现了copy出一个新对象的方法,调用 [person copy] 就可以了
那么对原对象或者现对象的操作都不会互相影响了
在调用 Person *p2 = [person copy]; 后 release p2 就能实现对象的回
收(p2 和 方法体内的 newPerson 指向的是同一个内存) [ps: 又有一个知识点,指向同一个内存的指针无论有多少个,计数器都不会+1]
当person作为一个方法的属性时 setter和getter的方法如下
- (void)setPerson:(NSString *)person { if (_person != person) { [_person release]; _person = [person copy]; } } - (NSString *)person
autorelease:
不自动释放 而是交给 autoreleasepool (延迟释放)自动释放池 : 讲对象所有权交给最近的NSAutoreleasepool 对象
[pool drain] 把释放池内的垃圾回收(一般不再使用)
[pool release] 把释放池都失去
原则上 尽可能用release
还有一个便利构造器的内存管理
+(id)personWithName:(NSString *)name age:(int)age sex:(NSString *)sex { Person *p = [[Person alloc ] initWithName:name age:age sex:sex]; return [p autorelease]; } { return [[_person retain] autorelease];}
这个也是使用了自动释放.
2自动管理内存(ARC ios5 新特性)
主要实现就是上面的autorelease, ARC模式是一种自动管理内存的模式,不用手动管理.
3内存泄露的几个情况
内存泄露 : 只开辟 不清除
过度释放: 释放之后还释放
野指针: 释放后 还在使用
补充一个@class
@class 声明一个类,主要用于.h文件中 让文件可以声明这个对象
等到用这个对象的方法时 再在.m 文件import
效果: 提高编译效率(不会因某个类改变导致编译器要重新编译所有关于这个类的文件)
这就是今天所学的了,感觉OC的内存管理是一个很是需要理解和下功夫的地方,它没有java的简便,
却提供了比较灵活的地方 内存管理的是OC里面一个重要的地方,需要大量的练习和使用.