浅拷贝和深拷贝
浅拷贝
浅拷贝就是对内存地址的复制,让目标对象指针和原对象指针指向同一片内存空间,当内存销毁的时候,指向这片内存的几个指针需要重新定义,否则会变成野指针。
浅拷贝拷贝了原来对象的指针,使原对象的引用计数+1,并没有创建新的对象。
深拷贝
深拷贝就是拷贝对象的具体内容,并开辟新的内存地址,新对象与原对象值相同,但是内存地址不一样,两个对象并没有关联。
深拷贝拷贝了原对象的值,但是开辟了新的内存地址,创建后的新对象和原对象没有任何关系。
区别
深拷贝(内容拷贝)和浅拷贝(指针拷贝)的本质区别在于是否开辟了新的内存地址,是否影响了内存地址的引用计数。
copy 和 mutableCopy(以数组为例子)
- (void)testArrayCopy {
NSArray *originArray = [[NSArray alloc] initWithObjects:@"张三", @"李四", nil];
NSArray *copyArray = [originArray copy];
NSArray *mutableCopyArray = [originArray mutableCopy];
NSLog(@"originArray: %p --- %@ --- %@", originArray, originArray.class, originArray);
NSLog(@"copyArray: %p --- %@ --- %@", copyArray, copyArray.class, copyArray);
NSLog(@"mutableCopyArray: %p --- %@ --- %@", mutableCopyArray, mutableCopyArray.class, mutableCopyArray);
NSMutableArray *originalMutableArray = [[NSMutableArray alloc] initWithObjects:@"张三", @"李四", nil];
NSMutableArray *copyMutableArray = [originalMutableArray copy];
NSMutableArray *mutableCopyMutableArray = [originalMutableArray mutableCopy];
NSLog(@"originArray: %p --- %@ --- %@", originalMutableArray, originalMutableArray.class, originalMutableArray);
NSLog(@"copyArray: %p --- %@ --- %@", copyMutableArray, copyMutableArray.class, copyMutableArray);
NSLog(@"mutableCopyArray: %p --- %@ --- %@", mutableCopyMutableArray, mutableCopyMutableArray.class, mutableCopyMutableArray);
}
打印结果:
originArray: 0x60000026a1e0 --- __NSArrayI --- (
"\U5f20\U4e09",
"\U674e\U56db"
)
copyArray: 0x60000026a1e0 --- __NSArrayI --- (
"\U5f20\U4e09",
"\U674e\U56db"
)
mutableCopyArray: 0x600000c6be70 --- __NSArrayM --- (
"\U5f20\U4e09",
"\U674e\U56db"
)
originArray: 0x600000c61d40 --- __NSArrayM --- (
"\U5f20\U4e09",
"\U674e\U56db"
)
copyArray: 0x60000026a480 --- __NSArrayI --- (
"\U5f20\U4e09",
"\U674e\U56db"
)
mutableCopyArray: 0x600000c625b0 --- __NSArrayM --- (
"\U5f20\U4e09",
"\U674e\U56db"
)
由打印结果可知:
1、对不可变集合对象的 copy 为浅拷贝,拷贝的指针指向原有对象的地址 0x60000026a1e0
2、对不可变集合对象的 mutableCopy 为深拷贝,复制的对象为可变对象__NSArrayM,返回一个新的集合对象
3、对可变集合对象的 copy 为深拷贝,复制对象为不可变对象 __NSArrayI,返回一个新的集合对象
4、对可变集合对象的 mutableCopy 为深拷贝,复制对象为可变对象__NSArrayM,返回一个新的集合对象
即:
| 对象类型 | 方法 | 拷贝后对象类型 | 拷贝类型 | 是否返回新对象 |
|---|---|---|---|---|
| NSArray | copy | NSArray | 浅拷贝 | 否 |
| NSArray | mutableCopy | NSMutableArray | 深拷贝 | 是 |
| NSMutableArray | copy | NSArray | 浅拷贝 | 是 |
| NSMutableArray | mutableCopy | NSMutableArray | 浅拷贝 | 是 |
NSCopying 协议
OC 中不是所有的类都支持拷贝,只有遵循了 NSCopying 协议的类才支持 copy,遵循了 NSMutableCopying 协议的类才支持 mutableCopy
@interface YZCopyPropertyModel : NSObject<NSCopying>
@property (nonatomic, copy) NSString *modelID;
@property (nonatomic, copy) NSString *modelMsg;
@end
@implementation YZCopyPropertyModel
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
YZCopyPropertyModel *model = [[YZCopyPropertyModel allocWithZone:zone] init];
model.modelID = self.modelID;
model.modelMsg = self.modelMsg;
return model;
}
@end
- (void)testCustomCopyClass {
YZCopyPropertyModel *model = [[YZCopyPropertyModel alloc] init];
model.modelID = @"1";
model.modelMsg = @"message";
YZCopyPropertyModel *model2 = [model copy];
NSLog(@"model: %p", model);
NSLog(@"model2: %p", model2);
}
结果:
model: 0x60000021a240
model2: 0x600000219cc0
由打印结果可知自定义类通过重写 copyWithZone 方法实现了深拷贝