1: 什么是深浅拷贝
- 苹果官方文档里:
There are two kinds of object copying: shallow copies and deep copies. The normal copy is a shallow copy that produces a new collection that shares ownership of the objects with the original. Deep copies create new objects from the originals and add those to the new collection.
翻译一下:
有两种类型的对象拷贝,浅拷贝和深拷贝。正常的拷贝,生成一个新的容器,但却是和原来的容器共用内部的元素,这叫做浅拷贝。深拷贝不仅生成新的容器,还生成了新的内部元素。
有官方文档为证, 我们可以得知: 浅拷贝复制容器,深拷贝复制容器及其内部元素
OC提供了copy和mutablecopy方法,顾名思义, copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象。
1: 系统的非容器类对象: 这里指的是NSString、NSNumber等等一类的对象。
NSString *str= @"origion";
NSString *strCp = [str copy];
NSMutableString *strMCp = [str mutableCopy];
[strMCp appendString:@"!!"];
NSLog(@"str: %@", str); // str: origion
NSLog(@"strCp: %@", strCp); // strCp: origion
NSLog(@"strMCp: %@", strMCp); // strMCp: origion!!
NSLog(@"str: %p", str); // str: 0x100004020
NSLog(@"strCp: %p", strCp); // strCp: 0x100004020
NSLog(@"strMCp: %p", strMCp); // strMCp: 0x1010219d0
}
调用copy之后系统并没有开辟新内存, 调用mutableCopy之后系统开辟了新内存, 所以对于这中非容器类对象来说:copy指的是浅拷贝, mutableCopy指的是深拷贝.
2: 系统的容器类对象, 指NSArray,NSDictionary等
- 2.1 对于
容器类本身上述结论也适用: 类型 | copy | mutableCopy | | -------------- | ---- | ----------- | | NSArray | 浅拷贝 | 深拷贝 | | NSMutableArray | 深拷贝 | 深拷贝
NSArray *arr = [NSArray arrayWithObjects:@"a", nil];
NSArray *arrCp = [arr copy];
NSMutableArray *arrMCp = [arr mutableCopy];
[arrMCp addObject:@"b"];
NSLog(@"arr: %@", arr); // arr: (a)
NSLog(@"arrCp: %@", arrCp); // arrCp: (a)
NSLog(@"arrMCp: %@", arrMCp); // arrMCp: (a, b)
NSLog(@"arr: %p", arr); // arr: 0x101114ed0
NSLog(@"arrCp: %p", arrCp); // arrCp: 0x101114ed0
NSLog(@"arrMCp: %p", arrMCp); // arrMCp: 0x1011199d0
- 2.2 容器内对象是
深拷贝还是浅拷贝? 例如数组中嵌套数组:
NSMutableArray *element = [NSMutableArray arrayWithObject:@1];
NSMutableArray *arr = [NSMutableArray arrayWithObject:element];
NSMutableArray *arrMCp = [arr mutableCopy];
[arrMCp addObject:@2];
[arrMCp[0] addObject:@3];
NSLog(@"arr: %@", arr); // arr:((1, 3))
NSLog(@"arrMCp: %@", arrMCp); //arr:((1, 3), 2)
NSLog(@"arr: %p", arr); // arr: 0x105243120
NSLog(@"arrMCp: %p", arrMCp); // arrMCp: 0x1052431f0
NSLog(@"arr[0]: %p", arr[0]); // arr[0]: 0x1052430f0
NSLog(@"arrMCp[0]: %p", arrMCp[0]); // arrMCp[0]: 0x1052430f0
从上面的例子, 可以得出结论: 所有系统容器类内的对象copy或mutableCopy方法, 都是浅拷贝
- 2.3 那么我们可以继续探索一下对于容器类内的对象该怎么实现
深拷贝呢? - 方法1: 用系统中的
initWithArray:copyItems:方法 - 方法2: 用我们自定义的方法例如:
- (NSArray *)test_deepCopy {
NSMutableArray *array = [NSMutableArray array];
for (id element in self) {
id copyElement = nil;
if ([element respondsToSelector:@selector(test_deepCopy)]) {
copyElement = [element test_deepCopy];
}
else if ([element respondsToSelector:@selector(copyWithZone:)]) {
copyElement = [element copy];
}
else {
copyElement = element;
}
[array addObject:copyElement];
}
NSArray *result = [NSArray arrayWithArray:array];
return result;
}
- (NSMutableArray *)test_mutableDeepCopy {
NSMutableArray *array = [NSMutableArray array];
for (id element in self) {
id copyElement = nil;
if ([element respondsToSelector:@selector(test_mutableDeepCopy)]) {
copyElement = [element test_mutableDeepCopy];
}
else if ([element respondsToSelector:@selector(mutableCopyWithZone:) {
copyElement = [element mutableCopy];
}
else if ([element respondsToSelector:@selector(copyWithZone:)]) {
copyElement = [element copy];
}
else {
copyElement = element;
}
[array addObject:copyElement];
}
return array;
}