weakSelf & strongSelf

循环引用

循环引用不做过多的解释,两个对象互相持有对方,谁都无法先被释放掉。循环引用经常是由于使用block而引起的,解决这种循环引用的方案主要是weakSelfstrongSelf。那具体为什么这两个Self可以解决循环引用呢?在这里用简单解释下。

block强引用self

首先看一下什么情况下block会强引用self。我们知道block在内存中有三种存放区域:

  • 全局区:声明为全局变量的block
  • 栈区: 方法中声明的block,未被拷贝的。
  • 堆区: 经过copy操作的block,会被复制到堆区。

blockcopy到堆区的过程中,会对block内部直接或者间接(引用self的实例变量)引用的selfretain操作。如果恰巧这个block是被self持有的,这种情况下则发生了循环引用。

weakSelf

为了避免循环引用的产生,可以通过__weak关键字,创建一个变量weakSelf,引用但不持有self,在self被释放的时候这个变量自动变为nil。简单来说就是这个变量不会导致self的引用计数+1,但是可以通过这个变量访问self。这样在block中使用weakSelf的时候,只是会引用weakSelf这个变量,就不会产生循环引用问题了。

strongSelf

利用weakSelf其实已经解决了循环引用的问题,但是在block中使用weakSelf时会有问题:weakSelf不一定什么时候会变为nil。因为block没有强引用self,所以self可能在block执行过程中被释放,此时weakSelf也会变为nil,这样很可能出现问题。

所以理想的情况是block在开始执行时,要么self已经是释放了,要么self一直存在,直到block执行完。所以这个时候就出现了strongSelf,即建立一个__strong关键字修饰的临时变量,strongSelf会对weakSelf指向的self做retain操作,保证在block执行过程中self不会被释放。

不过还有一点需要注意的是,weakSelf可能在block执行开始前就已经释放掉了,这样在block执行时,strongSelf的值也可能为nil,所以block中最好还是加上if (strongSelf)的判断。

疑问

这里有个疑问,strongSelf在这里又强引用了self,这样是不是又发生了循环引用呢?
答案是没有循环引用,因为strongSelf是一个临时变量,即局部变量,这个局部变量在block执行完毕后就释放掉了,这样对self的强引用也自然就没有了。

你可能感兴趣的:(weakSelf & strongSelf)