深拷贝与浅拷贝
浅拷贝
- 浅拷贝 (shallow copy) 特点:不会复制所引用的对象,其新复制的对象只是一个指针,指向现有的引用对象上.(其实就相当于 Windows 系统下的快捷方式的复制)
下面举一个简单地例子来分别下深拷贝与浅拷贝:
//创建两个可变的字符串
NSMutableString *student = [[NSMutableString alloc] initWithString:@"ZhangSan"];
NSMutableString *anotherStu= [[NSMutableString alloc] initWithString:@"LiSi"];
// 使用两个可变的字符串来创建数组,也就是组里的有两个元素,其元素类型是可变字符串
NSArray *students = @[student,anotherStu];
// 用创建好的数组copy一份赋值给另外一个数组
NSArray *copyStu = [students copy];
// 打印原数组和复制得到的数组的内容
NSLog(@"before moidfy the students:%@ and copyStu:%@",students,copyStu);
// 修改复制后得到的数组的第一个元素的值
[copyStu[0] appendString:@"-TeacherZhang"];
// 打印原数组的值, 查看是否发生了变化
NSLog(@"after modify copyStu: the students info:%@",students);
打印出结果是before moidfy the students:(
ZhangSan,
LiSi
) and copyStu:(
ZhangSan,
LiSi
)
after modify copyStu: the students info:(
“ZhangSan-TeacherZhang”,
LiSi
)
这就是浅拷贝,只是拷贝了一个指针,并没有拷贝一个完整的对象.
深拷贝
- 深拷贝 (deep copy)
特点:真正意义上的复制概念.得到的结果是多个,而非只是对象的引用. (对象的完全复制,包括其中的方法)
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 定义了一个不可变字符串
NSString *str = @"hello";
//打印出 str 的地址
NSLog(@"str‘s address:%p",str);
//通过mutableCopy协议可以将不可变的字符串转化为可变字符串
NSMutableString *anotherStr = [str mutableCopy];
NSLog(@"anotherStr‘s address:%p",anotherStr);
[anotherStr appendString:@"qingyun"];
NSLog(@"anotherString:%@",anotherStr);
NSMutableString *mStr = [[NSMutableString alloc] initWithString:@"HELLO"];
NSLog(@"mStr‘s address:%p",mStr);
// 通过copy协议可以将可变字符串转换为不可变字符串
NSMutableString *anotherMStr = [mStr copy];
NSLog(@"anotherMStr‘s address:%p",anotherMStr);
[anotherMStr appendString:@"-QINGYUN"];
}
return 0;
}
自定义对象的拷贝
实现自定义对象的拷贝的前提是必须要实现协议,否则,自定义对象调用 copy 对象的时候会发生崩溃的现象.
实例来说明这个问题,创建一个 QYCar 的类继承自 NSObject, 且遵从 NSCopying 协议,在 main.m 中实现自定义对象的 copy
在 QYCar 的头文件中,代码如下:
#import <Foundation/Foundation.h>
@interface QYCar : NSObject <NSCopying>
@property (nonatomic, strong)NSString *name;
@property (nonatomic, assign)NSInteger year;
@end
在 QYCar.m 中的代码如下:
#import "QYCar.h"
@implementation QYCar
//开箱即用的初始化方式
- (instancetype)init
{
self = [super init];
if (self) {
self.name = @"BWM";
self.year = 2013;
}
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"name:%@,year:%ld", self.name,self.year];
}
- (id)copyWithZone:(NSZone *)zone
{
QYCar *carCopy;
carCopy = [QYCar allocWithZone:nil];
carCopy.name = self.name;
carCopy.year = self.year;
return carCopy;
}
@end
在 main.m 中建立一个对象 car, 并调用开箱即用的初始化方式,然后再新建一个对象 carCopy, 并把 car 的内容 copy 给 carCopy, 为了显示我们成功拷贝了 car, 更改 carCopy 的 name 属性,并打印出来,显示下我们这是深拷贝.
int main(int argc, const char * argv[]) {
@autoreleasepool {
QYCar *car = [[QYCar alloc] init];
NSLog(@"car:%@",car);
QYCar *carCopy = [car copy];
carCopy.name = @"HeNanCar";
NSLog(@"carCopy:%@",carCopy);
NSLog(@"car again : %@",car);
}
return 0;
}
输出的结果是:
2015-07-01 21:06:43.302 SelfWithCopy[2631:2055248] car:name:BWM,year:2013
2015-07-01 21:06:43.303 SelfWithCopy[2631:2055248] carCopy:name:HeNanCar,year:2013
2015-07-01 21:06:43.303 SelfWithCopy[2631:2055248] car again : name:BWM,year:2013
版权声明:本文为博主原创文章,未经博主允许不得转载。