———-android培训、Java培训、iOS培训,期待与您交流———-
一、基本概念
copy分为copy和mutableCopy,即复制和可变复制
基本复制
浅复制,实际上只是复制了地址,新对象和旧对象的引用计数都会加一。
代码举例:
NSString *str = @"abc";
NSString *str2 = [str copy];
NSLog(@"%@",str2);//->abc
可变复制
深复制,实际上创建了新的对象,新对象的引用计数为1,旧对象的引用计数为原值。
NSString *str = @"abc";
NSMutableString *str2 = [str mutableCopy];
[str2 appendString:@"xxx"];
NSLog(@"%@",str2);//->abcxxx
关于复制后的新对象的可变性:
普通对象–>普通复制–>普通对象--不可变
普通对象–>普通复制–>可变对象--不可变
普通对象–>可变复制–>普通对象--不可变
普通对象–>可变复制–>可变对象--可变
可变对象–>普通复制–>普通对象--不可变
可变对象–>普通复制–>可变对象--不可变
可变对象–>可变复制–>普通对象--不可变
可变对象–>可变复制–>可变对象--可变
可以看出,无论何种情况,只有通过可变复制复制到可变对象的对象才是可变的。
二、为自定义类实现copy操作
自定义的类默认是不能使用copy的,需要手动实现。
实现步骤:
遵守\
-(id)copyWithZone:(NSZone*)zone{
NSLog(@"执行了copy方法");
Person *p = [[Person alloc]init];
p.name = self.name;
return p;
}
三、关于@property中的参数copy
当出现如下情况
Person *p = [Person new];
NSMutableString *str = [NSMutableString stringWithString:@"abb"];
p.name = str;
[str appendString:@"ccc"];
NSLog(@"%@",p.name);
当str值改变时,p.name也会跟着改变,而如果不想让p.name的值随str改变,修改Person类,将@property(nonatomic,retain)的参数retain改为copy,这样,在每次对p.name赋值时都会创建一个副本,将值赋值给这个副本。实现这个目的实际上是改写了set方法:
-(void)setName:(NSString*)name
{
if (_name !=name) {
[_name release];
_name = [name copy];
}
}
@property内存管理策略的选择
1.非ARC
- copy : 只用于NSString\block
- retain : 除NSString\block以外的OC对象
- assign : 基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用
- retain,一端用assign
2.ARC
- copy : 只用于NSString\block
- strong : 除NSString\block以外的OC对象
- weak : 当2个对象相互引用,一端用strong,一端用weak 4> assgin : 基本数据类型、枚举、结构体(非OC对象)