准备iOS开发iOS 的那些事儿

关于Block用copy修饰的原因的一点自己的理解

2018-08-08  本文已影响226人  CyanCricket

先说结论:

ARC中在block作为属性时用copy修饰是MRC时代的遗留物,是一个习惯问题,提示程序猿这里可能有内存问题。在ARC中用copy保留这个习惯.
在ARC中,copy是可以用strong来代替的。(注意:这里只是说可以,并不推荐,接着往下看...)

block在内存中的存放位置

OC中的三种类型的block:

block块的存放位置可能在3个地方:

MRC下:
全局区(代码区)、堆区、栈区

ARC下:
全局区、堆区
ARC下栈区会自动拷贝到堆区,因此ARC下只有这两个地方

代码区类型block:不访问栈区以外的变量(如局部变量),也不访问堆区的变量(如alloc创建的对象),这种时候block放在代码区;
堆区类型的block:访问了外部变量,此时block存放在堆区;

注意

这就可以理解到block的定义:

block:可以理解为匿名的函数,就是预先准备好的一段代码。只不过这段代码里面包含的东西比较多,有isa指针、flags、invoke、descriptor、variables;

所以要用strong替代copy修饰block要满足两个条件:

用strong修饰且引用了外部变量

另外:

一个block要使用self,会处理成在外部声明一个weak变量指向self,在block里又声明一个strong变量指向weakSelf?????
原因:block会把写在block里的变量copy一份,如果直接在block里使用self,(self对变量默认是强引用)self对block持有,block对self持有,导致循环引用,所以这里需要声明一个弱引用weakSelf,让block引用weakSelf,打破循环引用。
而这样会导致另外一个问题,因为weakSelf是对self的弱引用,如果这个时候控制器pop或者其他的方式引用计数为0,就会释放,如果这个block是异步调用而且调用的时候self已经释放了,这个时候weakSelf已就变成了nil。
当控制器(也可以是其他的控件)pop回来之后(或者一些其他的原因导致释放),网络请求完成,如果这个时候需要控制器做出反映,需要strongSelf再对weakSelf强引用一下。
但是,你可能会疑问,strongSelf对weakSelf强引用,weakSelf对self弱引用,最终不也是对self进行了强引用,会导致循环引用吗。不会的,因为strongSelf是在block里面声明的一个指针,当block执行完毕后,strongSelf会释放,这个时候将不再强引用weakSelf,所以self会正确的释放。

上一篇下一篇

猜你喜欢

热点阅读