深拷貝和淺拷貝蘋果官網上的解釋如下:
There are two kinds of object copying: shallow copies and deep copies. The normal copy is a shallow copy that produces a new collection that shares ownership of the objects with the original. Deep copies create new objects from the originals and add those to the new collection.
In the case of these objects, a shallow copy means that a new collection object is created, but the contents of the original collection are not duplicated—only the object references are copied to the new container.
A deep copy duplicates the compound object as well as the contents of all of its contained objects.
淺拷貝不會創建新的對方和原有對象共享同一個對象,深拷貝會將原有對象進行賦值,生成完全獨立的對象.
Copy 與 MutableCopy
iOS 深拷貝和淺拷貝可以通過Copy和MutableCopy來闡述,先來看兩段網上的經典代碼:
<pre><code>`- (void)copyTest {
NSString *string = @"FlyElephant";
NSString *copyString = [string copy];
NSMutableString *mutableCopyString = [string mutableCopy];
[mutableCopyString appendString:@"test"];
NSLog(@"NSString原始指針:%p copy之后的指針 = %p mutableCopy之后的指針 = %p", string, copyString, mutableCopyString);
}
-
(void)mutaleCopyTest {
NSMutableString *string = [[NSMutableString alloc] initWithString:@"FlyELephant"];
NSMutableString *copyString = [string copy];
NSMutableString *mutableCopyString = [string mutableCopy];NSLog(@"NSMutableString原始指針:%p copy之后的指針 = %p mutableCopy之后的指針 = %p", string, copyString, mutableCopyString);
[mutableCopyString appendString:@"test"];
NSLog(@"原始字符串:%@---copy之后的字符串:%@---mutalbeCopy之后的字符串:%@",string,copyString,mutableCopyString);
}`</code></pre>
通過以上例子我們似乎可以得出以下結論:
不可變對象: 不可變對象執行Copy的時候是指針賦值屬于淺拷貝,MutableCopy是內容復制屬于深拷貝.
可變對象: 可變對象在執行Copy和MutableCopy的時候都是內容復制屬于深拷貝.
再來看一段代碼:
<pre><code>` NSMutableString *str1 = [NSMutableString stringWithString:@"FlyElephant"];
NSMutableString *str2 = [NSMutableString stringWithString:@"Keso"];
NSMutableString *str3 = [NSMutableString stringWithString:@"Objective-C"];
NSMutableString *str4 = [NSMutableString stringWithString:@"Swift"];
NSLog(@"str1:%p str2:%p str3:%p str4:%p", str1,str2,str3,str4);
NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:
str1,
str2,
str3,
str4,
nil
];
NSMutableArray *dataArray2 = [dataArray mutableCopy];
NSMutableString *mStr;
mStr = dataArray[0];
[mStr appendString:@"--append"];
NSLog(@"dataArray:%@",dataArray);
NSLog(@"dataArray2:%@",dataArray2);
[dataArray addObject:@"test"];
NSLog(@"dataArray:%@",dataArray);
NSLog(@"dataArray2:%@",dataArray2);`</code></pre>
可變數組經過mutableCopy之后如果深拷貝,那么作為獨立的對象,數組之間應該是沒有影響的.
再來看一段代碼:
<pre><code>` NSMutableString *str1 = [NSMutableString stringWithString:@"FlyElephant"];
NSMutableString *str2 = [NSMutableString stringWithString:@"Keso"];
NSMutableString *str3 = [NSMutableString stringWithString:@"Objective-C"];
NSMutableString *str4 = [NSMutableString stringWithString:@"Swift"];
NSLog(@"str1:%p str2:%p str3:%p str4:%p", str1,str2,str3,str4);
NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:
str1,
str2,
str3,
str4,
nil
];
NSMutableArray *dataArray2 = [dataArray mutableCopy];
NSMutableString *mStr;
mStr = dataArray[0];
[mStr appendString:@"--append"];
NSLog(@"dataArray:%@",dataArray);
NSLog(@"dataArray2:%@",dataArray2);
[dataArray addObject:@"test"];
NSLog(@"dataArray:%@",dataArray);
NSLog(@"dataArray2:%@",dataArray2);`</code></pre>
copy: 不可變對象執行Copy之后不會生成新的對象,對象會共享,可變對象執行Copy之后生成新的對象,而且新的對象不可變.屬于淺拷貝.
mutableCopy: 不可變對象和可變對象執行mutableCopy之后生成新的對象,復制內容到新的內存中,但是屬于淺拷貝.
屬性 與 自定義對象
iOS屬性中字符串使用copy比較頻繁,定義兩個屬性字符串,來對比一下與strong的區別:
<pre><code>`@property (copy, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *infoDetail;`</code></pre>
測試代碼:
<pre><code>` NSMutableString *test = [[NSMutableString alloc] initWithString:@"FlyElephant"];
self.name = test;
self.infoDetail = test;
NSLog(@"name:%@----description:%@",self.name,self.infoDetail);
[test appendString:@"test"];
NSLog(@"name:%@----description:%@",self.name,self.infoDetail);`</code></pre>
屬性如果是字符串建議使用copy屬性,避免如果是可變復制,屬性發生變化.
自定義對象如果要實現拷貝,需要實現NSCopying協議:
<pre><code>`@interface Course()<NSCopying>
@end
@implementation Course
- (id)copyWithZone:(NSZone *)zone {
Course *course = [[Course allocWithZone:zone] init];
course.courseName = [self.courseName mutableCopy];
return course;
}
@end`</code></pre>
自定義對象拷貝:
<pre><code>` Course *course = [[Course alloc] init];
course.courseName = @"iOS 學習開發";
Course *copyCourse = [course copy];
NSLog(@"Course:%@----課程名字:%p",course,course.courseName);
NSLog(@"CopyCourse: %@----課程名字:%p",copyCourse,copyCourse.courseName);`</code></pre>
自定義對象拷貝,要記得屬性的拷貝.