1.先说字符串.假设对象持有如下两个属性
@property (nonatomic, strong) NSString *strStrong;
@property (nonatomic, copy) NSString *strCopy;
然后做如下操作1
```
NSMutableString *str = [NSMutableString stringWithFormat:@"%@",@"3333"];
self.strCopy= str;
self.strStrong= str;
NSLog(@"\n%p\n%p\n%p",str,self.strStrong,self.strCopy);
```
得到的结果如下
0x6000038e9b30
0x6000038e9b30
0xcefcc275fcf19ade
也就是说对于可变字符串,关键字strong只是引用计数器加1,strong后的指针指向原来的存储空间。copy后是新开一个存储空间。而且很重要的一点,copy的对象类型是不可变字符串,就是NSString类型。那strong不用说啦,还是可变类型。
那么对于NSString,使用copy和strong用什么不同吗?请看下面例子
NSString*str =@"33";
self.strCopy= str;
self.strStrong= str;
NSLog(@"\n%p\n%p\n%p",str,self.strStrong,self.strCopy);
结果如下
0x107cd8078
0x107cd8078
0x107cd8078
就是说,对于NSString,不管使用copy还是strong,都只是引用计数器加1。不会开辟新的内存空间。而且类型都是NSString类型的。就是说对于NSString类型,你的关键字是copy还是strong,影响不是那么大。但是考虑到多态特性,NSString类型可能指向NSMutableString类型的对象,建议字符串类型还是使用copy吧。
总结如下:使用copy之后,对于不可变字符串来说,不会新开内存空间,跟strong作用一样。但是对于可变字符串来说,copy是新开一个内存空间的,且新创建的对象是不可变字符串,strong是引用计数器加1,类型不变。
2.再说下数组
NSArray*arr =@[@"23",@"45"];
NSArray*arr2 = [arr copy];
NSArray*arr3 = [arr mutableCopy];
NSLog(@"%p\n%p\n%p",arr,arr2,arr3);
对应的值如下
0x6000036e7220
0x6000036e7220
0x6000038e9800
说明,不可变数组使用copy只是浅拷贝,就是原对象引用计数器加1,在内存中没有新开辟一个空间。而mutableCopy,原对象引用计数器不累加,但是新开了一个内存空间,是个深拷贝。而且copy后的类型还是不可变数组,mutableCopy之后的对象类型是可变数组
那么对于可变数组的copy和mutableCopy又是怎么样?请看下面的例子
NSMutableArray *arrM = [NSMutableArray arrayWithObjects:@"33",@"55", nil];
NSArray*arrM2 = [arrM copy];
NSArray*arrM3 = [arrM mutableCopy];
NSLog(@"%p\n%p\n%p",arrM,arrM2,arrM3);
对应的值如下
0x6000038e9b00
0x6000036e7160
0x6000038e9860
说明可变数组不管使用copy还是mutableCopy,都会新开一个内存空间。而且copy后的对象类型是不可变数组,mutableCopy之后的是可变数组。也就是说可变数组的的拷贝都是深拷贝
总结如下:对于不可变数组,copy只是引用计数器加1,不开辟新的内存空间,跟strong作用一样。mutableCopy开辟新的内存空间。对于可变数组,不管使用copy还是mutableCopy,都会新开一个内存空间。而且copy后的对象类型是不可变数组,mutableCopy之后的是可变数组。
对于字符串和数组使用copy的共同特点是,不可变类的使用copy只是引用计数器加1;可变类型的使用copy会新开一个内存空间,但是类型是不可变类型。
strong对于可变数组只是引用计数器加1.有兴趣的朋友可以在MRC环境下验证。