—【Copy 与 Strong 的正确使用姿势】—
了解 Copy 与 Strong 的区别需要从内存管理方面知识切入。Strong是ARC下引入的修饰,相当于手动管理内存(MRC)下的retain,在相关代码下,常常看到有的人用copy修饰NSString,NSArray,NSDictionary…等存在可变与不可变之分的对象,常常会用copy,而不是strong。下面我们使用OC语言代码来解释一下strong与copy的区别:
【拓展:什么是深拷贝?什么是浅拷贝?】
深拷贝:内存复制,即copy了多个不同内存,这些内存互不干涉,互不影响。
浅拷贝:指针复制,即copy了多个内存指针来指向同一块内存。
【不可变的NSString实验】
声明两个NSString属性变量:
@property (nonatomic, strong) NSString *str1;
@property (nonatomic, copy) NSString *str2;
创建两个不可变的NSString对象:
NSString *strA = @"I am A";
NSString *strB = @"I am B";
对两个NSString属性赋值:
self.str1 = strA;
self.str2 = strB;
打印内存地址:
NSLog(@"\r ✅ 第1⃣️组 Strong \r str1指针地址: %p \r strA指针地址: %p \r ✅",self.str1,strA);
NSLog(@"\r ✅ 第2⃣️组 Copy \r str2指针地址: %p \r strB指针地址: %p \r ✅",self.str2,strB);
打印结果如下:
✅ 第1⃣️组 Strong
str1指针地址: 0x107cb61a8
strA指针地址: 0x107cb61a8
✅
✅ 第2⃣️组 Copy
str2指针地址: 0x107cb61c8
strB指针地址: 0x107cb61c8
✅
【实验总结】
无论是copy还是strong修饰,指向内容的内存地址是一样,所以他们进行的是浅拷贝。
【可变的NSMutableString实验】
声明两个NSString属性变量:
@property (nonatomic, strong) NSString *str1;
@property (nonatomic, copy) NSString *str2;
创建两个不可变的NSString对象:
NSMutableString *strA = [NSMutableString stringWithString:@"I am A"];
NSMutableString *strB = [NSMutableString stringWithString:@"I am B"];
对两个NSString属性赋值:
self.str1 = strA;
self.str2 = strB;
打印内存地址:
NSLog(@"\r ✅ 第1⃣️组 Strong \r str1指针地址: %p \r strA指针地址: %p \r ✅",self.str1,strA);
NSLog(@"\r ✅ 第2⃣️组 Copy \r str2指针地址: %p \r strB指针地址: %p \r ✅",self.str2,strB);
打印结果如下:
✅ 第1⃣️组 Strong
str1指针地址: 0x60000368ce70
strA指针地址: 0x60000368ce70
✅
✅ 第2⃣️组 Copy
str2指针地址: 0xe5b6ac6236737c25
strB指针地址: 0x60000368cc90
✅
【实验总结】
Strong修饰的对象内存地址和可变字符串的对象内存地址是一样的,他们进行的是浅拷贝;Copy修饰的对象内存地址和可变字符串的对象内存地址是完全不同的内存地址,他们进行的是深拷贝;
【结论】
综上所述,在不可变对象之间进行转换,strong与copy作用是一样的,但是如果在不可变与可变之间进行操作,那么就比较推荐copy,这也就是为什么很多地方用copy,而不是strong修饰NSString,NSArray等存在可变不可变之分的类对象了,避免出现意外的数据操作.