A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© paradise6 中级黑马   /  2015-7-27 08:42  /  720 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

属性的特性: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"对象,而之前的引用不能被释放,这就造成了内存的泄露。
您需要登录后才可以回帖 登录 | 加入黑马