copy和mutableCopy
copy和mutableCopy之間的差異主要和深拷貝和淺拷貝有關(guān),先看一下深拷貝、淺拷貝的概念。
深拷貝、淺拷貝
所謂淺拷貝,在Objective-C中可以理解為引用計(jì)數(shù)加1,并沒有申請(qǐng)新的內(nèi)存區(qū)域,只是另外一個(gè)指針指向了該區(qū)域。深拷貝正好相反,深拷貝會(huì)申請(qǐng)新的內(nèi)存區(qū)域,原內(nèi)存區(qū)域的引用計(jì)數(shù)不變。看圖來說明深拷貝和淺拷貝的區(qū)別。

首先A指向一塊內(nèi)存區(qū)域,現(xiàn)在設(shè)置B = A

現(xiàn)在B和A指向了同一塊內(nèi)存區(qū)域,即為淺拷貝。
我們?cè)賮砜纯瓷羁钾?/p>

首先A指向一塊內(nèi)存區(qū)域,現(xiàn)在設(shè)置B = A
A和B指向的不是同一塊內(nèi)存區(qū)域,只是這兩塊內(nèi)存區(qū)域中的內(nèi)容是一樣的,即為深拷貝。
可變對(duì)象的copy、mutableCopy
- (void)testMutableCopy
{
NSMutableString *str1 = [NSMutableString stringWithString:@"abc"];
NSString *str2 = [str1 copy];
NSMutableString *str3 = [str1 mutableCopy];
NSLog(@"str1 = %p str2 = %p str3 = %p",str1,str2,str3);
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@"a",@"b", nil];
NSArray *array2 = [array1 copy];
NSMutableArray *array3 = [array1 mutableCopy];
NSLog(@"array1 = %p array2 = %p array3 = %p",array1,array2,array3);
}
可變對(duì)象的copy和mutableCopy都是深拷貝,那么輸出結(jié)果就是:
2019-02-01 13:01:27.525064+0800 TestClock[9357:143436] str1 = 0x60000086d8f0 str2 = 0xc8c1a5736a50d5fe str3 = 0x60000086d9b0
2019-02-01 13:01:27.525064+0800 TestClock[9357:143436] array1 = 0x600000868000 array2 = 0x60000067e5a0 array3 = 0x600000868030
我們可以看到,只要是可變對(duì)象,無論是集合對(duì)象,還是非集合對(duì)象,copy和mutableCopy都是深拷貝。
不可變對(duì)象的copy、mutableCopy
- (void)testCopy
{
NSString *str1 = @"123";
NSString *str2 = [str1 copy];
NSMutableString *str3 = [str1 mutableCopy];
NSLog(@"str1 = %p str2 = %p str3 = %p",str1,str2,str3);
NSArray *array1 = @[@"1",@"2"];
NSArray *array2 = [array1 copy];
NSMutableArray *array3 = [array1 mutableCopy];
NSLog(@"array1 = %p array2 = %p array3 = %p",array1,array2,array3);
}
不可變對(duì)象的copy是淺拷貝,mutableCopy是深拷貝,那么輸出結(jié)果就是:
2019-02-01 13:01:27.525064+0800 TestClock[9442:147133] str1 = 0x1045612b0 str2 = 0x1045612b0 str3 = 0x6000017e4450
2019-02-01 13:01:27.525064+0800 TestClock[9442:147133] array1 = 0x6000019f5c80 array2 = 0x6000019f5c80 array3 = 0x6000017e1170
可以看到,只要是不可變對(duì)象,無論是集合對(duì)象,還是非集合對(duì)象,copy都是淺拷貝,mutableCopy都是深拷貝。
自定義對(duì)象如何支持copy方法
項(xiàng)目開發(fā)中經(jīng)常會(huì)有自定義對(duì)象的需求,那么自定義對(duì)象是否可以copy呢?如何支持copy?
自定義對(duì)象可以支持copy方法,我們所需要做的是:自定義對(duì)象遵守NSCopying協(xié)議,且實(shí)現(xiàn)copyWithZone方法。NSCopying協(xié)議是系統(tǒng)提供的,直接使用即可。
- 遵守NSCopying協(xié)議:
@interface Student : NSObject <NSCopying>
{
NSString *_sex;
}
@property (atomic, copy) NSString *name;
@property (nonatomic, copy) NSString *sex;
@property (nonatomic, assign) int age;
@end
- 實(shí)現(xiàn)CopyWithZone方法:
- (instancetype)initWithName:(NSString *)name age:(int)age sex:(NSString *)sex
{
if(self = [super init]){
self.name = name;
_sex = sex;
self.age = age;
}
return self;
}
- (instancetype)copyWithZone:(NSZone *)zone
{
// 注意,copy的是自己,因此使用自己的屬性
Student *stu = [[Student allocWithZone:zone] initWithName:self.name age:self.age sex:_sex];
return stu;
}
- 測(cè)試:
- (void)testStudent
{
Student *stu1 = [[Student alloc] initWithName:@"Wang" age:18 sex:@"male"];
Student *stu2 = [stu1 copy];
NSLog(@"stu1 = %p stu2 = %p",stu1,stu2);
}
- 結(jié)果:
stu1 = 0x600003a41e60 stu2 = 0x600003a41fc0
這里是一個(gè)深拷貝,根據(jù)copyWithZone方法的實(shí)現(xiàn),應(yīng)該很容易明白為何是深拷貝。
除了NSCopying協(xié)議和copyWithZone方法,對(duì)應(yīng)的還有NSMutableCopying協(xié)議和mutableCopyWithZone方法,實(shí)現(xiàn)都是類似的,不做過多介紹。