objective-c - 使用 __block 和 __weak

标签 objective-c objective-c-blocks weak-references

我已经阅读了这个主题:What does the "__block" keyword mean?其中讨论了 __block 的用途,但我对其中一个答案感到困惑。它说 __block 用于避免保留循环,但它下面的评论让我不确定。

我正在这样使用它:

 self.someProperty = x; //where x is some object (id)
 __block __weak VP_User *this = self;

 //begin a callback-style block
     this.someProperty = nil;

我需要同时使用 __block__weak 吗?这样看起来有什么明显的问题吗?

最佳答案

__block 是一个存储限定符。它指定变量应该直接被 block 捕获而不是复制它。这在您需要修改原始变量的情况下很有用,如以下示例所示

__block NSString *aString = @"Hey!"; 
void(^aBlock)() = ^{ aString = @"Hello!" }; // without __block you couldn't modify aString
NSLog(@"%@", aString); // Hey!
aBlock();
NSLog(@"%@", aString); // Hello!

在 ARC 中,这会导致变量自动保留,因此可以在 block 实现中安全地引用它。在前面的示例中,当在 block 上下文中捕获时,aString 会收到一条 retain 消息。

请注意,这在 MRC(手动引用计数)中并非如此,其中引用变量而不保留。

将其标记为__weak会导致变量不被保留,所以block直接引用它而不保留它。这是潜在的危险,因为万一 block 的生命周期比变量长,因为它将引用垃圾内存(并且可能会崩溃)。

这是来自 clang doc 的相关段落:

In the Objective-C and Objective-C++ languages, we allow the __weak specifier for __block variables of object type. [...] This qualifier causes these variables to be kept without retain messages being sent. This knowingly leads to dangling pointers if the Block (or a copy) outlives the lifetime of this object.

最后,__block 可用于避免强引用循环(又名保留循环)的说法在 ARC 上下文中是完全错误的。由于在 ARC 中 __block 导致变量被强引用,因此实际上更有可能导致它们。

例如在 MRC 中,这段代码打破了一个保留周期

__block typeof(self) blockSelf = self; //this would retain self in ARC!
[self methodThatTakesABlock:^ {
    [blockSelf doSomething];
}];

而要在 ARC 中获得相同的结果,您通常会这样做

__weak typeof(self) weakSelf = self;
[self methodThatTakesABlock:^ {
    [weakSelf doSomething];
}];

关于objective-c - 使用 __block 和 __weak,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19227982/

相关文章:

ios - 多次单击按钮时无法旋转图像

ios - 从 NSMutableArray 动态显示 UILabel

objective-c - 如何使用 Objective C 在 iOS 中实现 GPS 功能?

ios - 尝试使用 NSTimer 为 UILabel 提供脉冲效果,但计时器始终相互冲突

iOS Swift 到 Objective-C 如何将弱引用传递给数组?

objective-c - 在 ARC 下,当通过属性分配给 ivar 时, block 是否会自动复制?

objective-c - 如何将 block 转换到 void *

objective-c - 当我不需要使用完成 block 时,如何在 swift 中声明 NULL/Void?

java - Scoped Variables 和 WeakReferences 奇怪地交互 - 有些对象没有得到垃圾收集

java - 从 WeakReference 列表中删除对象