天天看點

Objective-C 深拷貝與淺拷貝

深拷貝與淺拷貝

淺拷貝
  • 淺拷貝 (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

繼續閱讀