一、分成三组对比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修饰
示例代码:https://download.csdn.net/download/denggun12345/10768386