1、引用计数

在iOS中,使用引用计数来管理OC对象的内存一个新创建的OC对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间。

  1. // 创建出来引用计数是1
  2. Person *person = [[Person alloc] init];
  3. NSLog(@"%zd",person.retainCount);
  4. // release后引用计数变为0,内存被释放
  5. [person release];
  6. NSLog(@"end");
  1. ~: 1
  2. ~: -[Person dealloc]
  3. ~: end

*如果对象在不使用的时候没有调用release,就会造成内存泄漏

2、set方法

给Person类添加一个成员变量_dog

  1. @interface Person : NSObject {
  2. Dog *_dog;
  3. }

最简单的set方法如下面的代码所示,直接给_dog赋值

  1. - (void)setDog:(Dog *)dog {
  2. _dog = dog;
  3. }

但是如果外部创建dog后再release,dog就会被销毁,person就不能再继续使用dog,这样person和dog就没有持有关系了,需要在set方法里给dog调用retain方法,并在person销毁时,销毁内部成员变量_dog,保证person和成员变量_dog的生命周期保持一致:

  1. - (void)setDog:(Dog *)dog {
  2. _dog = [dog retain];
  3. }
  4. - (void)dealloc {
  5. // 销毁成员变量
  6. [_dog release];
  7. _dog = nil;
  8. // 父类的dealloc放在后面执行
  9. [super dealloc];
  10. }

这样还有一个问题就是当person重新设置一个新的dog时,之前设置的dog引用计数没有减1,会造成内存泄漏,所以需要在设置新dog时,对旧的dog执行release操作:

  1. - (void)setDog:(Dog *)dog {
  2. [_dog release]; // 旧dog 引用计数-1
  3. _dog = [dog retain]; // 新dog 引用计数+1
  4. }
  5. - (void)dealloc {
  6. // 销毁成员变量
  7. [_dog release];
  8. _dog = nil;
  9. // 父类的dealloc放在后面执行
  10. [super dealloc];
  11. }

如果person重复调用setDog并且传入的是同一个dog对象,就会对dog进行重复释放,所以在release前需要判断一下是否是同一个dog,set方法最终方案如下:

  1. - (void)setDog:(Dog *)dog {
  2. if (_dog != dog) { // 避免重复释放
  3. [_dog release];
  4. _dog = [dog retain];
  5. }
  6. }
  7. - (void)dealloc {
  8. // 销毁成员变量
  9. [_dog release];
  10. _dog = nil;
  11. // 父类的dealloc放在后面执行
  12. [super dealloc];
  13. }

*基本数据类型,不是oc对象没有自动引用计数,set方法直接赋值即可。

3、属性

给Person添加age、dog、car三个属性

  1. @interface Person : NSObject
  2. @property (nonatomic, assign) int age;
  3. @property (nonatomic, retain) Dog* dog;
  4. @property (nonatomic, retain) Car* car;
  5. @end

编译器会自动添加_开头的成员变量,并且添加set和get,在set方法内部实现引用计数相关操作。
在Person对象释放时,需要手动释放属性:

  1. - (void)dealloc {
  2. self.dog = nil;
  3. self.car = nil;
  4. [super dealloc];
  5. }

*在编译器自动添加成员变量前、需要使用@synthesize关键字,它可以设置属性的成员变量名称,并且会自动生成成员变量的setter、getter实现,例如: @synthesize age = _age;