先说结论

  • 可变对象的copy和mutableCopy都是深拷贝,mutableCopy是单层深拷贝
  • 不可变对象的copy是浅拷贝,mutableCopy是深拷贝
  • copy出来的是不可变对象,mutableCopy出来的是可变对象
  • 如果需要容器类完全深拷贝,容器内元素需要实现NSCopying和NSMutableCopying协议,并且使用带有copyItems的方法

测试

不可变对象

  1. - (void)testInmutable{
  2. NSLog(@"================================");
  3. NSLog(@" 不可变对象测试");
  4. NSLog(@"================================\n");
  5. Person *obj = [[Person alloc]init];
  6. NSArray *array = [NSArray arrayWithObject:obj];
  7. NSMutableArray *mutableArray = [array mutableCopy];
  8. NSArray *copyArray = [array copy];
  9. NSLog(@"-------------容器类-------------");
  10. NSLog(@"array: %p-%@ class:%@",array,array,NSStringFromClass([array class]));
  11. NSLog(@"copyArray: %p-%@ class:%@",copyArray,copyArray,NSStringFromClass([copyArray class]));
  12. NSLog(@"mutableArray: %p-%@ class:%@\n",mutableArray,mutableArray,NSStringFromClass([mutableArray class]));
  13. NSString *str = @"123";
  14. NSString *copyStr = [str copy];
  15. NSString *mutableStr = [str mutableCopy];
  16. NSLog(@"-------------非容器类-------------");
  17. NSLog(@"str: %p---%@ class:%@",str,str,NSStringFromClass([str class]));
  18. NSLog(@"copyStr: %p---%@ class:%@",copyStr,copyStr,NSStringFromClass([copyStr class]));
  19. NSLog(@"mutableStr: %p---%@ class:%@\n",mutableStr,mutableStr,NSStringFromClass([mutableStr class]));
  20. }

打印结果
截屏2021-01-14 15.24.29.png

可变对象

  1. - (void)testMutable{
  2. NSLog(@"================================");
  3. NSLog(@" 可变对象测试");
  4. NSLog(@"================================\n");
  5. Person *obj= [[Person alloc]init];
  6. obj.mName = @"name";
  7. NSMutableArray *array = [NSMutableArray arrayWithObject:obj];
  8. NSArray *copyArray = [array copy];
  9. NSMutableArray *mutableArray = [array mutableCopy];
  10. NSMutableArray *mutableArray1 = [NSMutableArray arrayWithArray:array];
  11. NSMutableArray *mutableArray2 = [[NSMutableArray alloc]initWithArray:array copyItems:YES];
  12. obj.mName = @"newName";
  13. NSLog(@"-------------容器类-------------");
  14. NSLog(@"array: %p-%@ class:%@ name:%@",array,array,NSStringFromClass([array class]),((Person *)[array firstObject]).mName);
  15. NSLog(@"copyArray: %p-%@ class:%@ name:%@",copyArray,copyArray,NSStringFromClass([copyArray class]),((Person *)[copyArray firstObject]).mName);
  16. NSLog(@"mutableArray: %p-%@ class:%@ name:%@",mutableArray,mutableArray,NSStringFromClass([mutableArray class]),((Person *)[mutableArray firstObject]).mName);
  17. NSLog(@"mutableArray1: %p-%@ class:%@ name:%@",mutableArray1,mutableArray1,NSStringFromClass([mutableArray1 class]),((Person *)[mutableArray1 firstObject]).mName);
  18. NSLog(@"mutableArray2: %p-%@ class:%@ name:%@\n",mutableArray2,mutableArray2,NSStringFromClass([mutableArray2 class]),((Person *)[mutableArray2 firstObject]).mName);
  19. NSMutableString *str = [NSMutableString stringWithString:@"123"];
  20. NSString *copyStr = [str copy];
  21. NSString *mutableStr = [str mutableCopy];
  22. NSLog(@"-------------非容器类-------------");
  23. NSLog(@"str: %p---%@ class:%@",str,str,NSStringFromClass([str class]));
  24. NSLog(@"copyStr: %p---%@ class:%@",copyStr,copyStr,NSStringFromClass([copyStr class]));
  25. NSLog(@"mutableStr: %p---%@ class:%@\n",mutableStr,mutableStr,NSStringFromClass([mutableStr class]));
  26. }

打印结果
截屏2021-01-14 15.29.24.png

开发时需要注意的

  • NSString,NSArray,NSDictionary类型的属性需要用copy修饰
    • 因为如果从mutable对象赋值后,copy会深拷贝mutable对象,并且变成不可变类型,这样在mutable对象再有增删操作时不会对copy修饰的属性造成影响,如果是strong修饰的属性就会跟着改变了。但是容器类因为是单层深拷贝,所以如果对元素的某个属性进行修改,copy后的对象也会被修改