使用__block和__weak
使用__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日
__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]; }];