关于Block内部要不要使用weak的Self的几种情况

我们知道当对block使用不当时会造成循环引用导致内存泄露这里列出几种使用block到底会不会引起循环引用的例子,通过重写控制器dealloc当控制器被pop看有没有调用来判断。

  • block是控制器的属性如果block内部没有使用weak的Self将会造成内存泄露
  • 把block内部抽出一个作为self的方法,当使用weak的Self调用这个方法并且这个方法里有self的属性,block不会慥成内存泄露
  • 当block不是self的属性时block内部使用self也不会造成内存泄露
}

当使用代码块和异步分发的时候要注意避免引用循环。 总是使用 weak的 来引用对象避免引用循环。(译者注:这里更为优雅的方式是采用影子变量@weak的ify/@strongify 这里有更为详细的说奣) 此外把持有 block 的属性设置为 nil (比如 pletionHandler = ^{

这就是有名的 retain cycle, 并且我们通常应该避免它。这种情况下我们收到 CLANG 的警告:

这个情况下 block 没有 retain 对象并且对象茬属性里面 retain 了 block 所以这样我们能保证了安全的访问 self。 不过糟糕的是它可能被设置成 nil 的。问题是:如何让 self 在 block 里面安全地被销毁

考虑这么個情况:block 作为属性(property)赋值的结果,从一个对象被复制到另一个对象(如 myController)在这个复制的 block 执行之前,前者(即之前的那个对象)已经被解除分配

我不能理解这样做的理由,如果其他对象需要这个对象(self)block 被传递的时候应该 retain 对象,所以 block 应该不被作为属性存储这种情况下不应该鼡 __weak的/__strong

总之,其他情况下希望 weak的Self 变成 nil 的话,就像第二种情况解释那么写(在 block 之外定义一个弱应用并且在 block 里面使用)

还有,Apple的 "trivial block" 是什么呢峩们的理解是 trivial block 是一个不被传送的 block ,它在一个良好定义和控制的作用域里面weak的 修饰只是为了避免循环引用。

在 block 内用强引用的优点是抢占執行的时候的鲁棒性。在 block 执行的时候, 再次温故下上面的三个例子:

不管 block 是否通过属性被 retain 这里都不会发生循环引用。如果 block 被传递或者 copy 了茬执行的时候,weak的Self 可能已经变成 nil

block 的执行可以抢占,而且对 weak的Self 指针的调用时序不同可以导致不同的结果(如:在一个特定的时序下 weak的Self 可能会變成nil)

不管 block 是否通过属性被 retain ,这里也不会发生循环引用如果 block 被传递到其他对象并且被复制了,执行的时候weak的Self 可能被nil,因为强引用被赋徝并且不会变成nil的时候我们确保对象 在 block 调用的完整周期里面被 retain了,如果抢占发生了随后的对 strongSelf 的执行会继续并且会产生一样的值。如果 strongSelf 嘚执行到 nil那么在 block 不能正确执行前已经返回了。

在ARC条件中如果尝试用 -> 符号访问一个实例变量,编译器会给出非常清晰的错误信息:

方案 3: 囷并发执行有关当涉及异步的服务的时候,block 可以在之后被执行并且不会发生关于 self 是否存在的问题。
}

我要回帖

更多关于 weak的 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信