问题描述
恐怕这个问题非常基础,但我认为它与许多涉足块的 Objective-C 程序员有关.
I'm afraid this question is pretty basic, but I think it's relevant to a lot of Objective-C programmers who are getting into blocks.
我听说,由于块捕获在它们内部引用的局部变量作为 const
副本,在块中使用 self
会导致保留循环,如果块被复制.所以,我们应该使用 __block
来强制块直接处理 self
而不是复制它.
What I've heard is that since blocks capture local variables referenced within them as const
copies, using self
within a block can result in a retain cycle, should that block be copied. So, we are supposed to use __block
to force the block to deal directly with self
instead of having it copied.
__block typeof(self) bself = self;
[someObject messageWithBlock:^{ [bself doSomething]; }];
而不仅仅是
[someObject messageWithBlock:^{ [self doSomething]; }];
我想知道的是:如果这是真的,有没有办法避免丑陋(除了使用 GC)?
What I'd like to know is the following: if this is true, is there a way that I can avoid the ugliness (aside from using GC)?
推荐答案
严格来说,它是一个 const 副本与这个问题无关.块将保留在创建时捕获的任何 obj-c 值.碰巧的是, const-copy 问题的解决方法与保留问题的解决方法相同;即,为变量使用 __block
存储类.
Strictly speaking, the fact that it's a const copy has nothing to do with this problem. Blocks will retain any obj-c values that are captured when they are created. It just so happens that the workaround for the const-copy issue is identical to the workaround for the retain issue; namely, using the __block
storage class for the variable.
无论如何,要回答您的问题,这里没有真正的替代方案.如果您正在设计自己的基于块的 API,并且这样做很有意义,您可以让块将 self
的值作为参数传递进来.不幸的是,这对大多数 API 来说没有意义.
In any case, to answer your question, there's no real alternative here. If you're designing your own block-based API, and it makes sense to do so, you could have the block get passed the value of self
in as an argument. Unfortunately, this doesn't make sense for most APIs.
请注意,引用 ivar 有完全相同的问题.如果您需要在块中引用 ivar,请改用属性或使用 bself->ivar
.
Please note that referencing an ivar has the exact same issue. If you need to reference an ivar in your block, either use a property instead or use bself->ivar
.
附录:当编译为 ARC 时,__block
不再中断保留循环.如果您为 ARC 编译,则需要使用 __weak
或 __unsafe_unretained
代替.
Addendum: When compiling as ARC, __block
no longer breaks retain cycles. If you're compiling for ARC, you need to use __weak
or __unsafe_unretained
instead.
这篇关于使用块保留“self"的循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!