1、直接用个简单的例子来深入了解set方法的内存管理分析吧,前提是禁掉arc。
a、有一个 Car 类,有一个 speed 的成员变量和一个公共的 run 方法;
b、还有一个 Person 类,拥有 Car 类对象和一个 drive 的方法;
2、Car 和 Person 类代码实现:
Car.h
#import@interface Car : NSObject@property int speed;- (void)run;@end
Car.m
#import "Car.h"@implementation Car- (void)run{ NSLog(@"汽车正以%d的速度行驶", _speed);}- (void)dealloc{ NSLog(@"%d速度的汽车被销毁了", _speed); [super dealloc];}@end
Person.h
#import#import "Car.h"@interface Person : NSObject{ Car *_car;}- (void)setCar:(Car *)car;- (Car *)car;- (void)drive;@end
Person.m
#import "Person.h"@implementation Person- (void)setCar:(Car *)car{ _car = car;}- (Car *)car{ return _car;}- (void)drive{ [_car run];}- (void)dealloc{ NSLog(@"人被销毁了"); [super dealloc];}@end
main.m
#import#import "Person.h"#import "Car.h"int main(int argc, const char * argv[]){ @autoreleasepool { Person *person = [[Person alloc] init]; Car *car = [[Car alloc] init]; car.speed = 100; person.car = car; [person drive]; [car release]; [person release]; } return 0;}
3、以上方法虽然没有内存泄露,但存在很多问题:
a、[car release] 方法一定要放在 [person release] 的前面,限制了car对象的使用,例如在 [car release] 后再次调用 [person drive] 便会报野指针错误;
b、再创建一个 car2 对象,并调用 person 的set方法,之前的car对象便会有内存泄露问题;
c、多次调用 person 的set方法存在内存泄露隐患问题;
4、于是我们将 Person 的set方法修改一下:
Person.m
- (void)setCar:(Car *)car{ if (_car != car) { [_car release]; _car = [car retain]; }}// 在person被回收之前release掉car对象- (void)dealloc{ [_car release]; NSLog(@"人被销毁了"); [super dealloc];}
5、这样在非arc机制下代码便更加符合内存管理,并不存在内存泄露等隐患。