这些关键字基本上是针对属性的set方法。
- strong:release旧值,retain新值,新值的retainCount+1;适用于基本的OC对象(除NSString外)
- assign:直接赋值,不更改retainCount。适用简单数据类型
- weak:同assign,但是区别与它的有一点,当用weak修饰的对象被别的变量释放,那么weak修饰的变量会被自动设置为nil,这样可以有效地防止崩溃。常用于解决循环引用。
- copy:set方法会先release旧值,再copy一个新的对象,reference count 为1;retain和copy的区别在于retain是对对象的引用计数+1,copy是创建一个新的对象。适用于block和NSString。
- unsafe_unretained:个人认为它与assign是等价的。
- strong、weak这两个关键词是在ARC时引入的。strong基本取代了MRC中的retain。至于strong和retain,究竟一不一样。网上很多人问,能讲清楚的没几个。不过我看过几个,说的是在修饰Block时,使用strong和retain会有截然不同的效果。strong会等于copy,而retain竟然等于assign!
闲言少叙,直接上代码
@interface Person : NSObject
@property (nonatomic, strong) NSObject *obj1;
@property (nonatomic, strong) NSObject *obj2;
@end
- (void)demo {
Person *p = [Person new];
p.obj1 = [NSObject new] ;
p.obj2 = p.obj1;
p.obj1 = nil;
NSLog(@"obj 1 = %@", p.obj1);
NSLog(@"obj 2 = %@", p.obj2);
}
【分析】
- Person *p = [Person new]; //开辟一块内存空间,指针P指向该内存空间,
- 经过p.obj2 = p.obj1;p.obj1与p.p.obj2指向同一地址,所以[NSObject new]所对应的retainCount为2
- 经过p.obj1 = nil;p.obj1指针指向NULL,[NSObject new]所对应的retainCount变为1,即仍有一个强指针指向(p.obj2)
【结果】
2017-04-26 16:29:10.740 08-weak&retain[4808:1281804] obj 1 = (null)
2017-04-26 16:29:10.740 08-weak&retain[4808:1281804] obj 2 = <NSObject: 0x60000001e170>
如果将上述的属性obj2改成weak
@interface Person : NSObject
@property (nonatomic, strong) NSObject *obj1;
@property (nonatomic, weak) NSObject *obj2;
@end
【结果】
2017-04-27 14:35:12.368 08-weak&retain[5805:1081448] obj 1 = (null)
2017-04-27 14:35:12.368 08-weak&retain[5805:1081448] obj 2 = (null)
【分析】
同样经过p.obj2 = p.obj1;p.obj1因为是strong所以指向[NSObject new]所对应的内存空间,但是p.obj2仅仅做了赋值,所以[NSObject new]所对应的retainCount仍为1
经过p.obj1 = nil;p.obj1指针指向NULL,[NSObject new]所对应的retainCount变为0,被内存回收。weak修饰的变量p.obj2被自动设置为nil
同样如果再把属性obj2改成unsafe_unretained
会直接crash在NSLog(@"obj 2 = %@", p.obj2);这句代码上,原因是因为他没有像weak一样置为nil。