属性的特性:copy和retain的区别
1. 属性特性retain和copy的对比:
@intertace Possession : NSObject
{
NSString *_possessionName;
NSString *_possessionClass;
}
//我们分别将两个属性设置成不同的特性,一个为retain, 一个为copy,这样为了做个对照。
@property (nonatomic, retain) NSString *possessionName;
@property (nonatomic, copy) NSString *possessionClass;
在生成的存方法中是这样的:
- (void)setPossessionName:(NSString *) possessionName
{
[possessionName retain]; //保留一份入参,这时候possessionName的ratain计数加1。
[_possessionName release]; //担心有一种情况出现(<1>标注),所以事先对实例变量进行释放,然后再做新的引用。
_possessionName = possessionName; //这时候 _possessionName和possessionName指向了一个地址(也就是一个对象
参数possessionName改变的时候,实例变量也会改变)
}
- (void)setPossessionClass:(NSString *) possessionClass
{
[_possessionClass release]; //担心有一种情况出现(<1>标注),所以事先对实例变量进行释放,然后再做新的引用。
_possessionClass = [possessionClass copy];
//这时候 _possessionName和possessionName指向的是不同的地址(也就是不同的对象),所以即使对入参进行改变,也不会引起实例变量的改变。
}
测试我们的结论:
//生成一个实例
Possession *p = [[Possession alloc] init];
NSMutableString *string = [NSMutableString stringWithString:@"Hello"];
[p setPossessionName:string];
[p setPossessionClass:string];
NSLog(@"%@,%@",p.possessionName,p.possessionClass);
//对string就行更改
[string appendString:@",World"];
//再打印一次
NSLog(@"%@,%@",p.possessionName,p.possessionClass);
这样两次打印的结果会让你明白copy和retain两个特性的明显区别
打印结果如下:
Hello,Hello
Hello,World,Hello
很明显:被加以retain特性的类属性,在外界参数改变的情况下它也随之改变,说明是共用了一块内存;
而加以copy特性的类属性,在外界参数改变的情况下它并没有随之改变,说明它只是copy了一份一模一样的内存内容。
得出的结论是:
如果属性的类型是可修改的子类(即该类的实例是可修改的),那么通常情况下,该属性应该有copy特性,而不是retain特性。
这样,类实例就可以拥有一份相应对象的完全独立的备份。
注:
<1> Possession *p = [[Possession alloc] init];
[p setPossessionName:@"Red"];
//接下来马上又赋一次值
[p setPossessionName:@"Black"];
这样的话实例变量指向@"Red"对象的引用还在,而又指向了@"Black"对象,而之前的引用不能被释放,这就造成了内存的泄露。