一. NSString 的copy和strong属性对比
iOS深浅拷贝
http://www.cocoachina.com/ios/20160803/17275.html
@property中如何使用内存特性copy和strong
http://www.qidiandasheng.com/2016/03/27/property-copy/
@interface TestStringClass ()
@property (nonatomic, strong) NSString *strongString;
@property (nonatomic, copy) NSString *copyedString;
@end
- (void)test {
NSString *originString = [NSString stringWithFormat:@"abc"];
self.strongString = originString;
self.copyedString = originString;
NSLog(@"origin string: %p, %p", originString, &originString);
NSLog(@"strong string: %p, %p", _strongString, &_strongString);
NSLog(@"copy string: %p, %p", _copyedString, &_copyedString);
}
打印出来:
-30 14:37:50.573 test[19357:5912951] origin string: 0xa000000006362613, 0x7fff50bfbc48
2015-08-30 14:37:50.574 test[19357:5912951] strong string: 0xa000000006362613, 0x7fe44961d790
2015-08-30 14:37:50.574 test[19357:5912951] copy string: 0xa000000006362613, 0x7fe44961d798
下面我们把NSString换成NSMutableString看看,将
NSString *originString = [NSString stringWithFormat:@"abc"];
改为:
NSMutableString *originString = [NSMutableString stringWithFormat:@"abc"];
输出结果:
2015-08-30 14:51:46.119 test[20229:5955951] origin string: 0x7fc27b47ff60, 0x7fff5c14cc48
2015-08-30 14:51:46.120 test[20229:5955951] strong string: 0x7fc27b47ff60, 0x7fc27b6433a0
2015-08-30 14:51:46.120 test[20229:5955951] copy string: 0xa000000006362613, 0x7fc27b6433a8
我们现在来想一下原因,当我们使用NSString的时候其实是不希望他改变的,那么我们一般情况下是使用copy,希望他进行深拷贝,那源字符串修改就不会影响到_copyedString了。但是如果源字符串也是NSString不可变的呢,那其实就算是浅拷贝也不会有什么影响了。 所以系统可能就在当源字符串为不可变类型时,你属性的内存特性为copy其实也只进行浅拷贝。当源属性为可变类型时,才进行深拷贝。
所以我们建议在使用NSString属性时使用copy,避免可变字符串的修改导致的一些非预期问题。
个人理解:
属性使用strong的时候,相当于指针拷贝。使用Strong修饰的时候,如果源属性可变,就会改变我们的数据。使用copy修饰的时候,源数据改变不会改变我们的数据。
二.property 属性
@property与@synthesize是成对出现的,可以自动生成某个类成员变量的存取方法。在Xcode4.5以及以后的版本,@synthesize可以省略。
1.atomic与nonatomic
atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题。
nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。
2.readwrite与readonly
readwrite:这个属性是默认的情况,会自动为你生成存取器。
readonly:只生成getter不会有setter方法。
readwrite、readonly这两个属性的真正价值,不是提供成员变量访问接口,而是控制成员变量的访问权限。
3.strong与weak
strong:强引用,也是我们通常说的引用,其存亡直接决定了所指向对象的存亡。如果不存在指向一个对象的引用,并且此对象不再显示在列表中,则此对象会被从内存中释放。
weak:弱引用,不决定对象的存亡。即使一个对象被持有无数个弱引用,只要没有强引用指向它,那么还是会被清除。
strong与retain功能相似;weak与assign相似,只是当对象消失后weak会自动把指针变为nil;
4.assign、copy、retain
assign:默认类型,setter方法直接赋值,不进行任何retain操作,不改变引用计数。一般用来处理基本数据类型。
retain:释放旧的对象(release),将旧对象的值赋给新对象,再令新对象引用计数为1。我理解为指针的拷贝,拷贝一份原来的指针,释放原来指针指向的对象的内容,再令指针指向新的对象内容。
copy:与retain处理流程一样,先对旧值release,再copy出新的对象,retainCount为1.为了减少对上下文的依赖而引入的机制。我理解为内容的拷贝,向内存申请一块空间,把原来的对象内容赋给它,令其引用计数为1。对copy属性要特别注意:被定义有copy属性的对象必须要符合NSCopying协议,必须实现- (id)copyWithZone:(NSZone *)zone方法。
也可以直接使用:
使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
使用copy: 对NSString
使用retain: 对其他NSObject和其子类