之前的编码中,对于NSString的property修饰,习惯性使用copy,只是粗略的知道copy属于深复制,retain/strong属于浅复制,并没有对其深究。最近需要详细了解这一块知识,在网上搜索相关内容,并且用代码验证,查看对比了内存地址,做一些总结。
一、之前对于copy和retain/strong的区别理解是这样的:
copy是复制了源对象所在内存空间的数据,放入目的对象指针指向的内存空间,并且令目的对象引用计数为1,对于源对象的引用计数没有影响;源对象内容的改变不会影响到目的对象。
retain/strong是目的对象指针指向源对象的内存空间,源对象的引用计数+1;源对象的改变会影响到目的对象。
mutablecopy返回的是可变的对象,copy返回的是不可变的对象。
二、代码验证探究
1、源对象为不可变 NSString
NSString*str = @"test";输出如下:
NSString* retainStr = [str retain];
NSString* copyStr = [str copy];
NSMutableString* mcopyStr = [str mutableCopy];
NSLog(@"str addr = %p",str);
NSLog(@"retainStr addr = %p",retainStr);
NSLog(@"copyStr addr = %p",copyStr);
NSLog(@"mcopyStr addr = %p",mcopyStr);
str addr = 0x4598
retainStr addr = 0x4598
copyStr addr = 0x4598
mcopyStr addr = 0x8caf630
分析:
retain的对象毫无悬念,还是源对象的内存地址;
copy的对象和我原来想的不一样,竟然和retain一样,也是源对象地址;这意味者并没有对源对象内容进行复制,而只是复制了指针而已。如此看来copy方法并不一定会复制源对象的内容。之所以复制,肯定是因为两个版本有所不同。而这里源对象是NSString不可变的,copy返回的也是不可变的,既然都不可变,那么这里的副本就没有多大意义存在,就如同使用字符串常量,系统会为我们优化,声明多个字符串,都是不可变且内容相同,那么系统就只申请一块内存,这个道理是一样的。指向一块内存就可以了,所以这里的copy和retain的作用是一样的。
mutablecopy的对象地址和源对象地址不同,说明重新开辟了内存,复制了一个副本。因为mutablecopy返回的对象是可变的,它的变动会影响到源对象,所以需要拷贝一份。
源对象为可变的NSMutableString
NSMutableString* str = [NSMutableString stringWithString:@"test"];输出结果如下:
NSString* retainStr = [str retain];
NSString* copyStr = [str copy];
NSMutableString* mcopyStr = [str mutableCopy];
NSLog(@"str addr = %p",str);
NSLog(@"retainStr addr = %p",retainStr);
NSLog(@"copyStr addr = %p",copyStr);
NSLog(@"mcopyStr addr = %p",mcopyStr);
str addr = 0x8b7a130
retainStr addr = 0x8b7a130
copyStr addr = 0x8b751d0
mcopyStr addr = 0x8b7a170
分析:
retain仍然和目的对象地址相同;
copy的地址和目的对象地址不相同,是因为源对象是可变的,目的对象不可变,当然需要两个不同的版本;
mutablecopy形成了一个新的副本。因为两个对象的改变会影响到对方,所以需要两个版本。
得到的结论:
1、对于copy来说,如果源对象是不可变的,那么是浅拷贝,没有必要深拷贝;如果源对象可变,为了安全性,深拷贝,生成副本。
2、对于mutablecopy来说,不管源对象是否可变,都是深拷贝。
因此我们在设置property的copy属性时,如果希望对象跟着源对象的值变化,那么就是用retain;如果希望对象保持独立的值,那就使用copy。当然这是在源对象为可变的情况下。
上面讨论的是NSString相关的retain/copy/mutablecopy,在oc里面所有实现了NSCopying和NSMutableCopying协议的类,都具有copy和mutablecopy这两个方法。这里引出了其他的oc对象的copy特性,它们是什么样的,下一篇进行探究。
欢迎指正!