在这个区块中强烈捕获“自我”可能会导致保留周期 [英] Capturing 'self' strongly in this block is likely to lead to a retain cycle

查看:171
本文介绍了在这个区块中强烈捕获“自我”可能会导致保留周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要阻止。但是编译器发出警告

I have reqest with block. But the compiler issues a warning


在这个区块中强烈捕获'自我'可能会导致保留
周期

"Capturing 'self' strongly in this block is likely to lead to a retain cycle"



__weak typeof(self) weakSelf = self;
[generalInstaImage setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:data[@"images"][@"low_resolution"][@"url"]]] placeholderImage:[UIImage imageNamed:@"Default"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
    NSLog(@"success");
    [generalInstaImage setImage: image];
    [weakSelf saveImage:generalInstaImage.image withName:data[@"id"]];

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
        NSLog(@"fail");
}];

我尝试写一下像 weakSelf.generalInstaImage ,但编译器会生成错误而不进行编译。

I try example write like weakSelf.generalInstaImage, but then the compiler generates an error and do not compile.

推荐答案

请考虑以下警告:


在此区块中强烈捕获 self 可能会导致保留
周期

Capturing self strongly in this block is likely to lead to a retain cycle

当您收到上述警告时,您应该查看您的区块:

When you receive the above warning, you should review your block for:


  • self 的任何明确引用;或

  • 引用任何实例变量引起的对 self 的任何隐式引用。

  • any explicit references to self; or
  • any implicit references to self caused by referencing any instance variables.

让我们假设我们有一个简单的类属性是一个块(这会遇到与你的问题相同的保留周期警告,但会让我的例子更简单一些):

Let's imagine that we have some simple class property that was a block (this will experience the same "retain cycle" warnings as your question, but will keep my examples a little simpler):

@property (nonatomic, copy) void (^block)(void);

我们假设我们想要在我们的块中使用其他类属性:

And let's assume we had some other class property we wanted to use inside our block:

@property (nonatomic, strong) NSString *someString;

如果你在块中引用 self (在下面的示例中,在访问此属性的过程中,您显然会收到有关保留周期风险的警告:

If you reference self within the block (in my example below, in process of accessing this property), you will obviously receive that warning about the retain cycle risk:

self.block = ^{
    NSLog(@"%@", self.someString);
};

通过您建议的模式补救,即:

That is remedied via the pattern you suggested, namely:

__weak typeof(self) weakSelf = self;

self.block = ^{
    NSLog(@"%@", weakSelf.someString);
};

不太明显,如果你引用一个实例变量,你也会收到保留周期警告块内的类,例如:

Less obvious, you will also receive the "retain cycle" warning if you reference an instance variable of the class inside the block, for example:

self.block = ^{
    NSLog(@"%@", _someString);
};

这是因为 _someString 实例变量携带对 self 的隐式引用,实际上相当于:

This is because the _someString instance variable carries an implicit reference to self, and is actually equivalent to:

self.block = ^{
    NSLog(@"%@", self->_someString);
};

你可能也倾向于尝试采用弱自我模式,但你不能。如果你尝试 weakSelf-> _someString 语法模式,编译器会警告你:

You might be inclined to try to adopt weak self pattern here, too, but you can't. If you attempt the weakSelf->_someString syntax pattern, the compiler will warn you about this:


由于竞争条件可能导致空值,因此不允许取消引用 __ weak 指针,将其分配给 strong 变量first

Dereferencing a __weak pointer is not allowed due to possible null value caused by race condition, assign it to strong variable first

因此,您可以使用 weakSelf 模式解决此问题,还要在块中创建一个本地 strong 变量,并使用它来取消引用实例变量:

You therefore resolve this by using the weakSelf pattern, but also create a local strong variable within the block and use that to dereference the instance variable:

__weak typeof(self) weakSelf = self;

self.block = ^{
    __strong typeof(self) strongSelf = weakSelf;

    if (strongSelf) {
        NSLog(@"%@", strongSelf->_someString);

        // or better, just use the property
        //
        // NSLog(@"%@", strongSelf.someString);
    }
};

顺便提一下,这个本地引用, strongSelf ,块内部还有其他优点,即如果完成块在不同的线程上异步运行,则不必担心 self 在块执行时被释放,导致意外后果。

As an aside, this creation of a local strong reference, strongSelf, inside the block has other advantages, too, namely that if the completion block is running asynchronously on a different thread, you don't have to worry about self being deallocated while the block is executing, resulting in unintended consequences.

这个 weakSelf / strongSelf 模式非常有用处理块属性并且您希望阻止保留周期(也称为强引用周期),但同时确保 self 无法在执行期间解除分配完成块。

This weakSelf/strongSelf pattern is very useful when dealing with block properties and you want to prevent retain cycles (aka strong reference cycles), but at the same time ensuring that self cannot be deallocated in the middle of the execution of the completion block.

仅供参考,Apple在使用终身限定符来避免强引用周期 过渡到ARC发行说明的部分。

FYI, Apple discusses this pattern in the "non-trivial cycles" discussion further down in the Use Lifetime Qualifiers to Avoid Strong Reference Cycles section of the Transitioning to ARC Release Notes.

您报告您收到了在您的示例中引用 weakSelf.generalInstaImage 时出现一些错误。这是解决此保留周期警告的正确方法,因此如果您收到某些警告,您应该与我们分享,并告诉我们您如何申报该财产。

You report that you received some "error" when you referenced weakSelf.generalInstaImage in your example. This is the correct way to resolve this "retain cycle" warning, so if you received some warning, you should share that with us, as well as show us how you declared the property.

这篇关于在这个区块中强烈捕获“自我”可能会导致保留周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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