iOS Developer

block与weakSelf、strongSelf

2016-07-20  本文已影响182人  luozhiwei

前言
这篇文章仅仅回答weakSelf、stongSelf是如何做到避免循环引用也延长执行生命周期的。
这个小技巧可能都被iOS工程师们用到滚瓜熟烂了,但同时也很可能有人还不知道原理的,所以小智就在这简单介绍一下!

避免循环引用?
全世界都知道block会自动强引用里面调用的实例变量,SO,一旦block里面所直接引用了self就会引发循环引用,为啥呢?


8306E75F-B76D-404D-A84C-7DF15C772385.png

如上图所示是一个直接强引用的示例图。OK,假设这时self想要释放自己,它的引用计数器必须清零,然后执行dealloc去释放掉它持有的属性与实例变量。
只是是不是看出点端倪来了。对了block是在dealloc的过程中执行的,在ARC环境下把这些代码都隐藏自动执行了。SO,因为block的强引用self,那么self的计数器就不会清零,就不会执行dealloc,不会执行dealloc,那么block的释放操作也不会执行,就形成了循环引用,造成self和block都不会被释放掉,内存泄漏。

那么引用引用了weakSelf呢?哈哈,如下图所示:


99C12EB6-2DD5-4D42-B3DD-8EE08350A222.png

我们继续从引入计数来分析这个问题。block引用了weakSelf,因为是weakSelf所以self的引用计数器完全不受block的影响。所以self在执行dealloc是爱咋地就咋地,只要count清零,就立即执行,还顺便释放掉block,所以weakSelf是能让实现避免循环引用的问题。

延长执行生命周期?

好像有weakSelf就能解决block的所有问题,这延长执行生命周期有是什么鬼?
好的,我们又来假设一种新的情况,假如你的block是个网络请求回调,而且这个回调是在非主线程异步执行,那么如果这时的self的count清零了,block中的回调都还未执行完就被清零了,这有时还是会影响业务逻辑的,要解决这个问题就需要引用strongSelf了,如下图所示:


375E678E-3C27-4F30-8422-F0E22F77C53C.png

细心的大家会发现stringSelf变蓝了,为什么不是变黄呢?那时因为红色代表block外部定义的属性变量,而蓝色表示是block中自己定义的局部变量。来到这里只要理清两个概念,即可解开这个谜题,

根据以上两点得出上图的简略图:


9BC85982-0F7A-4CB1-AC97-DB3652F37DB7.png

首先block只是在block只引用了weakSelf,所以不会引起循环引用。其次,每当block在执行的时候,因为它的局部变量间接强引用self,所以self的count不会清零而执行dealloc,确保了block能执行完成,一旦block执行完成,self又具备执行dealloc的权利,那么就能安全释放。

总结:
根据上文的原理阐述,发现通过weakSelf与strongSelf搭配使用,能决定一个block是否需要延长生命周期确保执行完毕。

上一篇下一篇

猜你喜欢

热点阅读