当使用代码块和异步分发的时候要注意避免引用循环。 总是使用 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 是否存在的问题。