果然还是对最基础的知识了解不透彻,今天看一看iOS中的两个修饰符:__block
和__weak
。也是做一下温习吧。
一、先说weak
,<弱引用>
我们知道weak
的使用,比如声明一个控件属性,就会用到weak
。
看代码:
1 | @property(nonatomic,weak)UILabel *label; |
当然这并不是说声明控件就一定使用weak
,相反的我在手动创建控件是大多数会使用strong
。但如果你比较细心的话,你会发现我们使用xib时,使用的却是weak
这一属性。那问题来了,我们使用strong
和 weak
的时机是何时呢?咱们接着往下看。
从storyboard
或者 xib
上创建控件
在控件放在view上的时候,已经形成了如下的引用关系,以
UILabel
为例:UIViewController->UIView->subView-> UILabel
,然后你为这个UILabel
声明一个weak
属性。
1 | @property(nonatomic,weak) IBOOutlet UILabel * label; |
相当于xib
对这个label
是强引用,你声明的属性对它是弱引用。
手动创建控件
- a). 将控件声明成
strong
1 | @property(nonatomic,strong) UIlabel * label; |
那么你在实现这个控件时只需这样:
1 | _label = [[UIlabel alloc]init]; |
- b). 将控件声明成weak
1 | @property(nonatomic,weak) UIlabel * label; |
那么你在实现这个控件时需要这样:
1 | UIlabel *label = [[UIlabel alloc]init]; |
关于block
循环引用的问题
由于block
会复制外部的变量,所以如果不注意,就会造成循环引用。对于这种情况,需要将引用的一方变成weak
,从而避免循环引用。
看代码:
1 | BlocksViewController *blockVC = [[BlocksViewController alloc]init]; |
二、strong
和weak
的区别
strong:强引用,也是我们通常说的引用,其存亡直接决定了所指向对象的存亡。如果不存在指向一个对象的引用,并且此对象不再显示在列表中,则此对象会被从内存中释放。
weak:弱引用,不决定对象的存亡。即使一个对象被持有无数个弱引用,只要没有强引用指向它,那么还是会被清除。
strong和copy是用来修饰强引用的属性,weak 用来修饰弱引用的属性;
strong、weak 需要ARC支持才能使用,copy不需要ARC支持
strong与retain功能相似;weak与assign相似,只是当对象消失后weak会自动把指针变为nil;
三、关于__block
先看一段代码:
1 | @autoreleasepool { |
我们现在看着可能得不出什么结论,那么,我们再看下面的代码,为了直观,我以图片的形式呈现:
现在对比就明显了。
下面总结一下:
a)
__block
对象在block
中是可以被修改、重新赋值的。b)
__block
对象在block
中不会被block
强引用一次,从而不会出现循环引用问题。c)
block
可以访问局部变量,但是不能修改。如果修改局部变量,需要加__block
,所以__block
是让修改外部变量的值.
对于 block 外的变量引用,block
默认是将其复制到其数据结构中来实现访问的
对于用 __block
修饰的外部变量引用,block
是复制其引用地址来实现访问的
四、block 和 weak修饰符的区别
__block
不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。__weak
只能在ARC模式下使用,也只能修饰对象(NSString)
,不能修饰基本数据类型(int)
。__block
对象可以在block
中被重新赋值,__weak
不可以。
链接: