发布
社区首页 >问答首页 >块可能会导致保留周期。

块可能会导致保留周期。
EN

Stack Overflow用户
提问于 2013-05-08 21:40:14
回答 3查看 2.6K关注 0票数 3

我为NSOperationBlock编写了以下类别

代码语言:javascript
代码运行次数:0
复制
@implementation NSOperationQueue (Extensions)

-(void)addAsynchronousOperationWithBlock:(void (^)(block))operationBlock
{
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    block signal = ^ {
        dispatch_semaphore_signal(semaphore);
    };

    [self addOperationWithBlock:^{
        operationBlock(signal);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_release(semaphore);
    }];
}

@end

它似乎正常工作,但是当我调用它时(如下面的片段所示),我会收到一个警告:

块可能会导致保留周期。

代码语言:javascript
代码运行次数:0
复制
[_queue addAsynchronousOperationWithBlock:^(block signal) {
        [self foo:nil];
         signal();
}];

foo是使用此类别的类的方法。

addOperationWithBlock:相同的代码(来自NSOperationQueue)没有显示警告:

代码语言:javascript
代码运行次数:0
复制
[_queue addOperationWithBlock:^ {
        [self foo:nil];
}];

我真的不明白。特别是我不明白的是:在这两种情况下,我真的应该使用弱指针吗?如果我不使用弱指针,这两个片段实际上会带来一个保留周期吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-13 14:13:32

把其他人在这里写的东西提取出来:

  1. 这两个代码示例都不会创建一个持久的保留周期,这将导致内存的串转。
  2. Xcode抱怨您的addAsynchronousOperationWithBlock方法,因为它有一个可疑的名称。它不抱怨addOperationWithBlock,因为它对addOperationWithBlock有特殊的了解,它可以克服它的怀疑。
  3. 要消除警告,请使用__weak (请参阅jszumski和matt的答案)或将addAsynchronousOperationWithBlock重命名为不以"add“或"set”开头。

详细说明以下几点:

  1. 如果self拥有_queue,那么您将有一个短暂的保留周期。self将拥有_queue,它将拥有这些块,调用[self foo:]的块将拥有self。但是,一旦这些块运行完毕,_queue就会释放它们,并且这个循环将被打破。
  2. 静态分析器已被编程为怀疑以"set“和"add”开头的方法名。这些名称表明,该方法可能永久保留已传递的块,可能会创建一个永久保留周期。因此,关于您的方法的警告。它并不抱怨-[NSOperationQueue addOperationWithBlock:],因为有人告诉它不要这样做,因为有人知道NSOperationQueue在运行它们之后释放块。
  3. 如果您使用__weak,分析器不会抱怨,因为不存在保留周期的可能性。如果您重命名您的方法,分析器不会抱怨,因为它没有任何理由怀疑您永久保留传递给它的块的方法。
票数 4
EN

Stack Overflow用户

发布于 2013-05-08 21:43:02

当您在块中使用self时,它会被块捕获,并可能导致保留周期。当self (或它具有强引用的内容)对块具有强引用时,就会发生循环。要避免潜在的循环,请声明一个弱指针并在块中使用该指针:

代码语言:javascript
代码运行次数:0
复制
YourClassName * __weak weakSelf = self;

[_queue addAsynchronousOperationWithBlock:^(block signal) {
    [weakSelf foo:nil];
}];
票数 9
EN

Stack Overflow用户

发布于 2013-05-09 02:19:44

jszumski的回答在本质上是正确的,但重要的是要使“弱我”舞蹈的形式正确。表格(基于他的代码)是:

代码语言:javascript
代码运行次数:0
复制
YourClassName * __weak weakSelf = self;

[_queue addAsynchronousOperationWithBlock:^(block signal) {
    YourClassName * strongSelf = weakSelf;
    if (strongSelf)
         [weakSelf foo:nil];
}];

因此,我们通过一个强引用捕获weakSelf。如果不这样做,weakSelf可能会在您使用它的过程中消失(因为您对它的引用很弱)。

请看我的关于舞蹈的书,以及其他你可以做的关于块引起的潜在保留周期的事情:

situations

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16450675

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档