最近有同学问我关于属性@property()的关键字assign,weak,strong,copy区别,这里总结一下,供大家参考。修饰代理等对象使用weak,修饰NSString、block使用copy,但很少思考为什么?这篇文章将会给大家揭开这层面纱。
1.assign 与weak区别
- assign适用于基本数据类型,weak是适用于NSObject对象,并且是一个弱引用。
- assign其实也可以用来修饰对象。那么我们为什么不用它修饰对象呢?因为被assign修饰的对象(一般编译的时候会产生警告:Assigning retained object to unsafe property; object will be released after assignment)在释放之后,指针的地址还是存在的,也就是说指针并没有被置为nil,造成野指针。对象一般分配在堆上的某块内存,如果在后续的内存分配中,刚好分到了这块地址,程序就会崩溃掉。
- 那为什么可以用assign修饰基本数据类型?因为基础数据类型一般分配在栈上,栈的内存会由系统自己自动处理,不会造成野指针。
weak修饰的对象在释放之后,指针地址会被置为nil。所以现在一般弱引用就是用weak。weak使用场景:
- 在ARC下,在有可能出现循环引用的时候,往往要通过让其中一端使用weak来解决,比如: delegate代理属性,通常就会声明为weak。
- 自身已经对它进行一次强引用,没有必要再强引用一次时也会使用weak。比如:自定义 IBOutlet控件属性一般也使用weak,当然也可以使用strong。
2.strong 与copy的区别
- strong 与copy都会使引用计数加1,但strong是两个指针指向同一个内存地址,copy会在内存里拷贝一份对象,两个指针指向不同的内存地址
3.__block与__weak的区别
-
__block是用来修饰一个变量,这个变量就可以在block中被修改
__block:使用 __block修饰的变量在block代码块中会被retain(ARC下会retain,MRC下不会retain)
__weak:使用__weak修饰的变量不会在block代码块中被retain
同时,在ARC下,要避免block出现循环引用 __weak typedof(self)weakSelf = self;
4.1 block变量定义时为什么用copy?block是放在哪里的?
- block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,可能被随时回收,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。通过copy可以把block拷贝(copy)到堆,保证block的声明域外使用。
特别需要注意的地方就是在把block放到集合类当中去的时候,如果直接把生成的block放入到集合类中,是无法在其他地方使用block,必须要对block进行copy。
[array addObject:[[^{
NSLog(@"hello!");
} copy] autorelease]];
4.2 block 为什么不用strong?
block如果用到了self,就会retain self,如果是strong的话,就造成了循环引用
官方文档:You should specify copy as the property attribute, because a block needs to be copied to keep track of its captured state outside of the original scope. This isn’t something you need to worry about when using Automatic Reference Counting, as it will happen automatically, but it’s best practice for the property attribute to show the resultant behavior
本文全属个人见解,如果您认为说法不正确或者哪里有错误的地方,请在评论中留言或者使用以下联系方式,笔者会在第一时间修正!!!
联系方式:QQ:983202699。