Objective-C 块内的代码如何引用块对象本身?
self 只是块内的捕获变量,并不引用块本身,那么块如何在没有显式捕获变量的情况下引用自身呢?
self
is merely a captured variable inside a block and doesn't reference the block itself, so how does a block reference itself without having an explicit captured variable for that purpose?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您使用
__block
,因为该块将在创建该块时复制strawberryFields
的值,该副本将在赋值之前.您还必须在任何其他复制操作之前
复制
该块,否则您最终会得到一个引用堆栈上原始版本的块。请注意,上面的代码泄漏了区块。在某个地方,需要
释放
该块来平衡副本。you use the
__block
because the block will make a copy of the value ofstrawberryFields
when the block is created which will be before the assignment.you also must
copy
the block prior to any other copy operation or else you'll end up with a block that references the on-stack original version.note that the above code leaks the block. Somewhere, there needs to be a
release
of that block to balance the copy.我发现这种模式对于 ARC(自动引用计数)来说既有效又稳定,无论是在调试还是发布版本中。
最初,我尝试将
__block
修饰符添加到myBlock
中,并直接使用该变量在块的实现中进行递归。这适用于 ARC 调试版本,但在发布版本上会因EXC_BAD_ACCESS
而中断。另一方面,删除 __block 修饰符会引发“被块捕获时未定义变量”警告(并且我不愿意运行它和测试)。I found this pattern to work and stable for ARC (automatic reference counting), both in Debug and Release builds.
Initially I tried just putting a
__block
modifier tomyBlock
and use that variable directly to recurse within the block's implementation. That works on the ARC Debug build but breaks with anEXC_BAD_ACCESS
on the Release build. On the other hand removing the__block
modifier raises a "variable not defined when captured by block" warning (and I was reluctant to run it and test).我以前从未尝试过此操作,并且不能 100% 确定它是否有用(如果有效),但例如:
您可能已使用 __block 声明变量以防止自保留循环。
I have never tried this before and not 100% sure it's useful, if valid, but for example:
You probably have declare the variable with __block to prevent self-retain cycle.
该块需要某种方法来消除它自己的引用。通常,这是通过将块存储在类的属性中来完成的。
有时您可能不想使用某个属性。以下是在没有属性的情况下如何执行此操作:
要记住的关键是所有代码路径都必须指向 block = nil。为此,我们每 5 秒调用一次该块,直到weakSelf 变为 nil。
The block needs some way to nil out its own reference. Typically it is done by storing the block in a property of the class.
Sometimes you can prefer to not use a property. Here is how you do it without a property:
The key thing to keep in mind is that all code paths must lead to a block = nil. We do that here by calling the block every 5 seconds until weakSelf turns nil.
请注意,在 ARC 中,情况略有不同 - 与 MRC 不同,ARC 中默认保留
__block
对象指针变量。这样,就会造成循环引用。该块有必要捕获对其自身的弱引用(使用__weak
),以避免出现保留周期。然而,我们仍然需要在某个地方对该块进行强引用。如果没有强引用,则该块(由于复制而位于堆上)将被释放。因此,我们需要两个变量,一强一弱,并在块内使用弱变量来引用自身:
Note that in ARC, it's a little different --
__block
object pointer variables are by default retained in ARC, unlike in MRC. Thus, it will cause a retain cycle. It is necessary for the block to capture a weak reference to itself (using__weak
) in order to not have a retain cycle.However, we still need a strong reference to the block somewhere. If there are no strong references, the block (which is on the heap since it's copied) will be deallocated. Thus, we need two variables, one strong and one weak, and inside the block use the weak one to reference itself: