如何正确使用property里面的strong,weak等关健字

来源:互联网 发布:怎么彻底卸载java 编辑:程序博客网 时间:2024/05/23 23:42

为了弄清楚怎么才能正确的使用propertystrongweak等关健字,咱们写一个类TTObject.

TTObject.h

@interface TTObject : NSObject@property (nonatomic, strong) NSString* string1;@property (nonatomic, copy) NSString* string2;@property (nonatomic, weak) NSString* string3;@property (nonatomic, assign) NSString* string4;@property (nonatomic, strong) NSArray* array1;@property (nonatomic, copy) NSArray* array2;@property (nonatomic, weak) NSArray* array3;@property (nonatomic, assign) NSArray* array4;@end

TTObject.m

@implementation TTObject@end

在app启动里面使用一下这个类。

TTObject* obj = [[TTObject alloc] init];    NSString* stringA = @"123abcd";    NSMutableString* stringB = [NSMutableString stringWithString:@"123abc"];    NSLog(@"NSString-------->:%p", stringA);    NSLog(@"NSMutableString->:%p", stringB);    NSLog(@"\n");    NSLog(@"右值为NSString:");    obj.string1 = stringA; //strong    obj.string2 = stringA; //copy    obj.string3 = stringA; //weak    obj.string4 = stringA; //assign    NSLog(@"strong--->string1:%p, class:%@", obj.string1,  [obj.string1 class]);    NSLog(@"copy----->string2:%p, class:%@", obj.string2,  [obj.string2 class]);    NSLog(@"weak----->string3:%p, class:%@", obj.string3,  [obj.string3 class]);    NSLog(@"assign--->string4:%p, class:%@", obj.string4,  [obj.string4 class]);    NSLog(@"\n");    NSLog(@"右值为NSMutabletring:");    obj.string1 = stringB; //strong    obj.string2 = stringB; //copy    obj.string3 = stringB; //weak    obj.string4 = stringB; //assign    NSLog(@"strong--->string1:%p, class:%@", obj.string1,  [obj.string1 class]);    NSLog(@"copy----->string2:%p, class:%@", obj.string2,  [obj.string2 class]);    NSLog(@"weak----->string3:%p, class:%@", obj.string3,  [obj.string3 class]);    NSLog(@"assign--->string4:%p, class:%@", obj.string4,  [obj.string4 class]);    NSArray* arrayA = @[@1, @2, @3];    NSMutableArray* arrayB = [arrayA mutableCopy];    NSLog(@"NSArray-------->:%p", arrayA);    NSLog(@"NSMutableArray->:%p", arrayB);    NSLog(@"\n");    NSLog(@"右值为NSArray:");    obj.array1 = arrayA; //strong    obj.array2 = arrayA; //copy    obj.array3 = arrayA; //weak    obj.array4 = arrayA; //assign    NSLog(@"strong--->array1:%p, class:%@", obj.array1,  [obj.array1 class]);    NSLog(@"copy----->array2:%p, class:%@", obj.array2,  [obj.array2 class]);    NSLog(@"weak----->array3:%p, class:%@", obj.array3,  [obj.array3 class]);    NSLog(@"assign--->array4:%p, class:%@", obj.array4,  [obj.array4 class]);    NSLog(@"\n");    NSLog(@"右值为NSMutabletring:");    obj.array1 = arrayB; //strong    obj.array2 = arrayB; //copy    obj.array3 = arrayB; //weak    obj.array4 = arrayB; //assign    NSLog(@"strong--->array1:%p, class:%@", obj.array1,  [obj.array1 class]);    NSLog(@"copy----->array2:%p, class:%@", obj.array2,  [obj.array2 class]);    NSLog(@"weak----->array3:%p, class:%@", obj.array3,  [obj.array3 class]);    NSLog(@"assign--->array4:%p, class:%@", obj.array4,  [obj.array4 class]);

这下面是Log:

2015-07-16 10:33:23.903 PropertyTest[2908:255095] NSString-------->:0x1023000b82015-07-16 10:33:23.904 PropertyTest[2908:255095] NSMutableString->:0x7fad09c6f0002015-07-16 10:33:23.904 PropertyTest[2908:255095] 2015-07-16 10:33:23.904 PropertyTest[2908:255095] 右值为NSString:2015-07-16 10:33:23.904 PropertyTest[2908:255095] strong--->string1:0x1023000b8, class:__NSCFConstantString2015-07-16 10:33:23.904 PropertyTest[2908:255095] copy----->string2:0x1023000b8, class:__NSCFConstantString2015-07-16 10:33:23.904 PropertyTest[2908:255095] weak----->string3:0x1023000b8, class:__NSCFConstantString2015-07-16 10:33:23.904 PropertyTest[2908:255095] assign--->string4:0x1023000b8, class:__NSCFConstantString2015-07-16 10:33:23.904 PropertyTest[2908:255095] 2015-07-16 10:33:23.905 PropertyTest[2908:255095] 右值为NSMutabletring:2015-07-16 10:33:23.905 PropertyTest[2908:255095] strong--->string1:0x7fad09c6f000, class:__NSCFString2015-07-16 10:33:23.905 PropertyTest[2908:255095] copy----->string2:0x7fad09d4d540, class:__NSCFString2015-07-16 10:33:23.905 PropertyTest[2908:255095] weak----->string3:0x7fad09c6f000, class:__NSCFString2015-07-16 10:33:23.911 PropertyTest[2908:255095] assign--->string4:0x7fad09c6f000, class:__NSCFString2015-07-16 10:33:23.911 PropertyTest[2908:255095] NSArray-------->:0x7fad09e209002015-07-16 10:33:23.911 PropertyTest[2908:255095] NSMutableArray->:0x7fad09e159202015-07-16 10:33:23.912 PropertyTest[2908:255095] 2015-07-16 10:33:23.912 PropertyTest[2908:255095] 右值为NSArray:2015-07-16 10:33:23.912 PropertyTest[2908:255095] strong--->array1:0x7fad09e20900, class:__NSArrayI2015-07-16 10:33:23.912 PropertyTest[2908:255095] copy----->array2:0x7fad09e20900, class:__NSArrayI2015-07-16 10:33:23.912 PropertyTest[2908:255095] weak----->array3:0x7fad09e20900, class:__NSArrayI2015-07-16 10:33:23.912 PropertyTest[2908:255095] assign--->array4:0x7fad09e20900, class:__NSArrayI2015-07-16 10:33:23.913 PropertyTest[2908:255095] 2015-07-16 10:33:23.913 PropertyTest[2908:255095] 右值为NSMutabletring:2015-07-16 10:33:23.913 PropertyTest[2908:255095] strong--->array1:0x7fad09e15920, class:__NSArrayM2015-07-16 10:33:23.913 PropertyTest[2908:255095] copy----->array2:0x7fad09d0d9d0, class:__NSArrayI2015-07-16 10:33:23.967 PropertyTest[2908:255095] weak----->array3:0x7fad09e15920, class:__NSArrayM2015-07-16 10:33:23.967 PropertyTest[2908:255095] assign--->array4:0x7fad09e15920, class:__NSArrayM

看了Log之后,咱们下面分别说说Strong,weak, copy, assgin这几个关健字的作用。

strong

当property使用strong时, 在调用Setter方法时,会强引用右值。猜想它的Setter方法实现应该是这样的:

 - (void)setString1:(NSString *)string1 {     if (_string1 != string1) {            _string1 = string1;       }     }   

那么问题来了,如果我们右值使用的是NSMutableString,必竟它也是NSString的字类啊,Xcode不会有任何警告提示。这样在Obj持有的string1成了一个NSMutableString的对象。如果我们在外部,用Gettter方法拿到obj.string1时,它是可以随意修改的。

copy

当property使用copy时, 在调用Setter方法时,会用右值的copy协议。猜想它的Setter方法实现应该是这样的:

- (void)setString2:(NSString *)string2 {    if (_string2 != string2) {        _string2 = [string2 copy];     } }

总是有一些新人会说,如果copy协议的话,会重新审请内存创建一个对象,然后将内容再付给它,(可以理解成C语言的1deep-copy1)那这样岂不是会加大的内存的使用啊。

看了上面log,我想这个困惑就解了吧。显然,string2使用copy的协议,当右值为NSString时,内存地址不变!! 是不是脑洞大开啊,原来这个不可变对象在调用copy时,根没处理一样,也就是说没有新生一个对象,很好很强大。

当右值为NSMutableString时,调用copy协议,地址变了,生成了新的对象,不过呢,这个对象是inmutable的,在外部Getter方法时,就不怕被修改了,只读特性保持住了。

weak

当property使用weak时, 在调用Setter方法时,会弱引用右值。

 - (void)setString3:(NSString *)string3 {     if (_string3 != string3) {        __weak NSString* string = string3;        _string3 = string;     } }

这个跟强引用是类似的,都是引用,只不过是弱的引用,因为它是弱引用,当右值没有对象强引用它时, obj.string3 就会被设为nil,没有ownership, 不持有,只是借用而用,不是自已的has-a, 仅仅use-a

除此之外stong引用出现的问题,它也有,右值是NSSMutableString是,也会被修改,也对,本来就拿来用用,人家改了,管你鸟事啊。

assign

当property不指定时,默认就是它,有代码洁癖的人如果是assign的话,一般不写,而有迫症的人,会写,一定要上下对齐,看着爽。

- (void)setString4:(NSString *)string4 {    if (_string4 !=string4) {       __unsafe_unretained NSString* string = string4;        _string4 = string;        }     }

看到没__unsafe_unretained,这个从字眼上就知道,不安全的持有,哇,好怕怕,在手动管理内存的年代,直接左值=右值就是assgin操作,到了ARC的年代,这种直接=成了strong的了。

根weak有几分相似啊,也算是一种引用啊,都是拿指针过来用用,use-a,与weak不同的是,unsafe的啊,如果右值这个string没了,dealloc了, 它还儍拿着用呢,相当于C里面野指针,你用了已经释放了的内存,如果运气好,
有时候会还能用几下,没几下就会BAD_ACCESS,哇崩掉了,崩崩更健康,成长之必经之路啊, 那个weak的,被置成nil了,哎呀我去,不崩,好啊,但是这种引发的bug,更难查好不好,好深的一颗雷就被这样埋下了。

如果把nil塞到array里或dictionary里也会异常。

总结:

现在你们在用基本数据模型(NSSArray, NSSet..)时,定义property属性时,选择哪种关健字应该很情楚了吧,无需记法则,掌握原理,其实也不难。

代码我已经上传到了github上了,小伙伴们可以自测^_^

0 0
原创粉丝点击