使用__block和__weak

22 浏览
0 Comments

使用__block和__weak

我阅读过这个帖子:\"什么是“__block”关键字?\",它讨论了__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吗?这种写法有什么明显的问题吗?

admin 更改状态以发布 2023年5月21日
0
0 Comments

如果你想在块中改变变量的值,应该使用__block

例如:

__block BOOL result = NO;
dispatch_sync(dispatch_get_main_queue(), ^{
  ...
  result = YES;
  ...
});

如果你想避免保留周期,应该使用__weak

例如:

__weak typeof(self) wself = self;
self.foobarCompletion = ^{
  ...
  wself.foo = YES;
  ...
};

如果有需要,你可以结合它们使用。

0
0 Comments

__block是一种存储修饰符。它指定变量应直接由块捕捉,而不是复制它。如果您需要修改原始变量,则此功能非常有用,如以下示例所示

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

在ARC中,这会自动保留变量,以便可以在块实现中安全地引用它。在前面的示例中,当在块上下文中捕获时,aString会发送retain消息。

请注意,在MRC(手动引用计数)中不是这样的,其中引用变量而无需保留它。

将其标记为__weak会导致不保留变量,因此块直接引用它但不保留它。这可能很危险,因为在块的生存期比变量长时,它将引用垃圾内存(很可能会崩溃)。

以下是clang文档中相关的段落:

在Objective-C和Objective-C ++语言中,我们允许使用__weak限定符来处理对象类型的__block变量。[...]这个限定符导致这些变量在没有发送保留消息的情况下保留。如果块(或副本)的生命周期超出此对象的生命周期,则明知这会导致悬垂指针。

最后,声称__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];
}];

0