1. 程式人生 > >深拷貝與淺拷貝;copy與mutableCopy;容器型別的深拷貝;copy和strong;

深拷貝與淺拷貝;copy與mutableCopy;容器型別的深拷貝;copy和strong;

一、分成三組對比NSMutableDictionary與NSDictionary;NSMutableString與NSString;NSMutableArray與NSArray分別呼叫copy和mutableCopy方法,檢視對應的物件的地址值判斷深淺拷貝;

1、字典:(示例程式碼 testDics方法,有四種組合)

self.mutableDic是NSMutableDictionary型別:

NSMutableDictionary *newMutDic = [self.mutableDic mutableCopy];//深

NSDictionary *newDic = [self.mutableDic copy];//深

self.dic是NSDictionary型別:

NSMutableDictionary *newMutDic = [self.dic mutableCopy];//深

NSDictionary *newDic = [self.dic copy];//淺

2、字串:(示例程式碼 testStrings方法,有四種組合)

self.mutableStr是NSMutableString型別:

 NSMutableString *newMutStr = [self.mutableStr mutableCopy];//深

NSString *newStr = [self.mutableStr copy];//深

self.str是NSString型別:

NSMutableString *newMutStr = [self.str mutableCopy];//深

NSString *newStr = [self.str copy];//淺

3、陣列:(示例程式碼 testArrays方法,有四種組合)

self.mutableArray是NSMutableArray型別:

  NSMutableArray *newMutArray = [self.mutableArray mutableCopy];//深

  NSArray *newArray = [self.mutableArray copy];//深

self.array是NSArray型別:

  NSMutableArray *newMutArray = [self.array mutableCopy];//深

  NSArray *newArray = [self.array copy];//淺

結論:根據以上1、2、3的程式碼可知,只有NS型別呼叫copy方法才是淺拷貝,其他的情況全是深拷貝

二、容器型別的例項的深拷貝:(示例程式碼testMutableArrayArray方法)

此處以陣列為例,只有在上邊一是陣列深拷貝的情況下為例:

NSMutableArray *newMuArrayArray = [self.mutableArrayArray mutableCopy];

[newMuArrayArray addObject:@[@"44",@"33"]];

[self.adArray addObject:@"3"];

NSArray *ss = newMuArrayArray[0];

 NSLog(@"%@ %p == %@ %p  == %@  %p  == %@  %p",self.mutableArrayArray,self.mutableArrayArray,newMuArrayArray,newMuArrayArray,self.adArray,self.adArray,ss,ss);

上述列印:self.adArray與ss的地址值相同;self.mutableArrayArray與newMuArrayArray地址值不同

結論:容器類(此處以陣列為例)呼叫copy或mutableCopy能出現的深拷貝的情況下,只是容器的深拷貝,而非容器內元素的深拷貝

三、用copy還是strong:(示例程式碼testStrongAndCopyStr方法)

如果你已經完全理解了上述一,這裡就非常好理解了:

宣告屬性為NSString:

@property (nonatomic,strong) NSString *strongString;

@property (nonatomic,copy) NSString *copString;

為屬性賦值:

NSMutableString *oriMuStr = [[NSMutableString alloc] initWithString:@"muStr原始的muStr"];

    self.strongString = oriMuStr;

    self.copString = oriMuStr;

改變oriMuStr的值:

NSRange r = {3,2};

    [oriMuStr replaceCharactersInRange:r withString:@"ooo"];

打log:NSLog(@"\n%@ %@ %@",self.strongString,self.copString,oriMuStr);

屬性為NSString型別時,self.copString沒有隨著oriMuStr的改變而改變,而self.strongString變了。

同理,當屬性為NSMutableString型別時:

宣告屬性:

@property (nonatomic,strong) NSMutableString *strongMutaString;

@property (nonatomic,copy) NSMutableString *copMutaString;

NSMutableString *oriMuStr = [[NSMutableString alloc] initWithString:@"muStr原始的muStr"];

    self.strongMutaString = oriMuStr;

    self.copMutaString = oriMuStr;

    NSRange r = {3,2};

    [oriMuStr replaceCharactersInRange:r withString:@"ooo"];

    NSLog(@"\n%@ %@ %@",self.strongMutaString,self.copMutaString,oriMuStr);

屬性為NSMutableString型別時,self.copMutaString沒有隨著oriMuStr的改變而改變,而self.strongMutaString變了。

綜上,結論:

無論是宣告NSString還是NSMutableString型別的屬性時,我們希望此屬性被賦值為NSMutableString型別的字串後,此屬性不會因這個可變型別字串的改變而改變(這也是多數情況下的用法),那就用copy修飾屬性

同理、其他相關型別亦是如此。

解析:宣告屬性時用copy和strong其實是重寫了屬性的set方法

例如屬性宣告為copy時的copString屬性的set方法如下:

-(void)setCopString:(NSString *)copString{

    _copString = [copString copy];//重寫set方法時,呼叫copy後,即使宣告屬性時不用copy關鍵字(用strong,strong是預設的,所以重寫set方法不加strong也預設是strong的)也有copy的作用

}

當NSString屬性的指標指向NSSMutableString時,其set方法是NSSMutableString的copy根據一中關於string型別的分析可知,此時是深拷貝,故不希望NSString型別的屬性在使用時發生不想要的改變的話,需要copy修飾