使用__block和__weak [英] Using __block and __weak

查看:84
本文介绍了使用__block和__weak的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读此线程:"__block"是什么?关键字的意思是什么?讨论了__block的用途,但我对答案之一感到困惑.它说__block用来避免保留周期,但是下面的注释使我不确定.

I've read over this thread: What does the "__block" keyword mean? which discusses what __block is used for but I'm confused about one of the answers. It says __block is used to avoid retain cycles, but the comments underneath it leave me unsure.

我正在使用类似这样的东西:

I'm using it something like this:

 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?用这种方式看起来有什么明显的问题吗?

Do I need to use both __block and __weak? Any glaring problems with this way this looks?

推荐答案

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

__block is a storage qualifier. It specifies that the variable should directly be captured by the block as opposed to copying it. This is useful in case you need to modify the original variable, as in the following example

__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消息.

In ARC this causes the variable to be automatically retained, so that it can be safely referenced within the block implementation. In the previous example, then, aString is sent a retain message when captured in the block context.

请注意,在不保留变量的情况下引用变量的MRC(手动引用计数)中,情况并非如此.

Note that this isn't true in MRC (Manual Reference Counting), where the variable is referenced without being retained.

将其标记为__weak导致不保留该变量,因此该块直接引用该变量,但不保留它.这有潜在的危险,因为如果块的寿命比变量长,因为它将引用垃圾内存(并可能崩溃).

Marking it as __weak causes the variable not to be retained, so the block directly refers to it but without retaining it. This is potentially dangerous since in case the block lives longer than the variable, since it will be referring to garbage memory (and likely to crash).

以下是 clang doc 的相关段落:

在Objective-C和Objective-C ++语言中,我们允许对象类型__block变量的__weak说明符. [...]此限定符使这些变量得以保留,而不会发送保留消息.如果该块(或副本)的寿命超过了该对象的寿命,则会有意导致悬空指针.

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中会导致强烈引用该变量,因此实际上更可能导致它们.

Finally the claim that __block can be used to avoid strong reference cycles (aka retain cycles) is plain wrong in an ARC context. Due to the fact that in ARC __block causes the variable to be strongly referenced, it's actually more likely to cause them.

例如在MRC中,此代码中断了保留周期

For instance in MRC this code breaks a retain cycle

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

通常要在ARC中获得相同的结果

whereas to achieve the same result in ARC, you normally do

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

这篇关于使用__block和__weak的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆