深拷貝與淺拷貝
淺拷貝
-
淺拷貝 (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[] 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 ;
}
自定義對象的拷貝
實作自定義對象的拷貝的前提是必須要實作協定,否則,自定義對象調用 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 = ;
}
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 ;
}
輸出的結果是:
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