关于C#:__ weak和__block引用有什么区别?

What is the difference between a __weak and a __block reference?

我正在阅读Xcode的文档,这让我感到困惑:

1
2
3
4
__block typeof(self) tmpSelf = self;
[self methodThatTakesABlock:^ {
    [tmpSelf doSomething];
}];

从文档中复制以下内容:

A block forms a strong reference to variables it captures. If you use
self within a block, the block forms a strong reference to self, so if
self also has a strong reference to the block (which it typically
does), a strong reference cycle results. To avoid the cycle, you need
to create a weak (or __block) reference to self outside the block, as
in the example above.

我不明白"弱者"(或__block)是什么意思?

1
__block typeof(self) tmpSelf = self;

1
__weak typeof(self) tmpSelf = self;

这里完全一样?

我在文件中发现了另一件事:

Note: In a garbage-collected environment, if you apply both __weak and
__block modifiers to a variable, then the block will not ensure that it is kept alive.

所以,我很困惑。


从关于块的文档

__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus, the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame (for example, by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.

从医生那里得知

__weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.

所以它们在技术上是不同的。_块是停止将变量从外部作用域复制到块作用域中。_弱指针是一个自定界的弱指针。

注意我说的技术上,因为对于你的情况,他们会做(几乎)同样的事情。唯一的区别是是否使用圆弧。如果您的项目使用ARC并且仅用于IOS4.3及更高版本,请使用"弱"。如果全局范围引用是以某种方式发布的,它确保引用设置为零。如果您的项目不使用ARC或用于较旧的操作系统版本,请使用块。

这里有一个微妙的区别,确保你理解它。

编辑:拼图的另一个部分是不安全的。此修改器几乎与uuu弱修改器相同,但适用于4.3之前的运行时环境。但是,它并没有设置为零,可能会留下挂起的指针。


In manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle.

苹果文档


在使用自我挡块时,应使用弱挡块,而不是保留自我挡块。

如果你需要强大的自我,那么你可以这样使用:

1
2
3
4
5
6
7
__weak typeof(self) *weakSelf = self;
[self methodThatTakesABlock:^{
    if (weakSelf) {
        __strong typeof(self) *strongSelf = weakSelf;
        [strongSelf doSomething];
    }
}];

除了关于__block__weak的其他答案外,还有另一种方法可以避免场景中的保留循环。

1
2
3
4
5
@weakify(self);
[self methodThatTakesABlock:^ {
    @strongify(self);
    [self doSomething];
}];

有关@weakify@strongify宏的详细信息