copy深/浅拷贝
即指针拷贝,是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,但是拷贝可变对象为深拷贝
mutableCopy深拷贝
即内容拷贝,指拷贝对象的具体内容,而内存地址是重新分配的,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉
mutableCopy
和copy
是一个方法,定义在NSObject
类中,用于拷贝对象
copy和mutableCopy
- 由于
NSString
的特殊性,其数据存放在常量区,同一数据指针指向的地址是一样的
NSString *str1 = @"str";
NSString *str2 = @"str";
NSLog(@"%p,%p",str1,str2);//同个地址
NSArray *arr1 = @[str1,str2];
NSArray *arr2 = @[str1,str2];
NSLog(@"%p,%p",arr1,arr2);//不同地址
输出结果:
2022-03-08 18:34:18.817479+0800 Music[6262:471008] 0x100b9c070,0x100b9c070
2022-03-08 18:36:47.801387+0800 Music[6302:473278] 0x600000135e20,0x600000136260
- 不可变数据做拷贝
// 不可变数据
NSArray *arr1 = @[@1,@2];
NSArray *arr2 = [arr1 copy]; // 浅拷贝
NSMutableArray *arr3 = [arr1 mutableCopy]; // 深拷贝
NSLog(@"%p,%p,%p",arr1,arr2,arr3);
输出结果:
2022-08-23 10:37:20.773046+0800 Music[7322:3133638] 0x282c1b560,0x282c1b560,0x282242610
- 可变数据做拷贝
// 可变数据
NSMutableArray *arr1 = [NSMutableArray array];
[arr1 addObject:@1];
NSArray *arr2 = [arr1 copy]; // 深拷贝
NSMutableArray *arr3 = [arr1 mutableCopy]; // 深拷贝
NSLog(@"%p,%p,%p",arr1,arr2,arr3);
输出结果:
2022-08-23 10:39:48.850628+0800 Music[7327:3135287] 0x281965470,0x281585ec0,0x281966b20
copy
是拷贝为不可变对象,mutableCopy
是拷贝为可变对象- 对不可变的数组、字典、集合等集合类对象,
copy
是指针拷贝,mutablecopy
是内容拷贝 - 对于可变的数组、字典、集合等集合类对象,
copy,mutablecopy
都是内容拷贝
字符串对象拷贝的引用计数器问题
- 存储在常量区的字符串对象是不允许被回收的,所以存储在常量区的字符串对象的引用计数器是一个超大是数,并且retain和release无效
- 若字符串存储在堆区,这个字符串对象和普通的对象是一样的,引用计数器默认是1
- 浅拷贝,对象的引用计数器+1,深拷贝,原来的对象的引用计数器不变,新对象引用计数器+1
自己的类具备对象拷贝能力
- copy方法内部调用了另一个方法copyWithZone,这个方法是定义在NSCoping协议之中
- 深拷贝:重新创建一个对象,复制返回
- 浅拷贝:直接返回self
@interface Person :NSObject<NSCoping>
...
@property(nonatomic,copy)NSString *name;
@end
@implementation Person
-(id)copyWithZone:(NSZone *)zone
{
//深拷贝
Person *p1 = [Person new];
p1.name = _name;
return p1;
//浅拷贝
return self;
}
属性中的strong和copy
- 属性中
copy
关键字的作用就是调用被赋值给属性的对象的copyWithZone
方法,并将返回值赋值给属性 - 对不可变的数组、字典、集合等集合类对象,都是指针拷贝
- 对于可变的数组、字典、集合等集合类对象,
strong
是指针拷贝,copy
是内容拷贝
// 可变数据举例
@property (nonatomic,strong) NSMutableString * StrongName;
@property (nonatomic,copy) NSMutableString * name;
----------------------------------------------------
NSMutableString *str = [NSMutableString new];
[str appendString:@"str"];
NSLog(@"%p,%@",str,str);
self.name = str;
self.StrongName = str;
[str appendString:@"!!!"];
NSLog(@"%p,%@",str,str);
NSLog(@"%p,%@",self.name,self.name);
NSLog(@"%p,%@",self.StrongName,self.StrongName);
----------------------------------------------------
输出结果:
2022-03-10 23:03:24.466102+0800 Music[3617:132644] 0x600000436250,str
2022-03-10 23:03:24.466167+0800 Music[3617:132644] 0x600000436250,str!!!
2022-03-10 23:03:24.466230+0800 Music[3617:132644] 0x963cbe8a3f6c64e4,str
2022-03-10 23:03:24.466274+0800 Music[3617:132644] 0x600000436250,str!!!