简体   繁体   English

保留循环,强烈引用dispatch_queue

[英]Retain cycle with strong reference to dispatch_queue

In a class, I've declared a thread like: 在一个类中,我已经声明了一个类似于的线程:

@property (nonatomic, strong) dispatch_queue_t databaseQueue;

and then I perform an operation this thread like 然后我执行这个线程的操作

dispatch_async(self.databaseQueue, ^{
        [self.dao deleteRetries];
    });

Can this potentially create a retain cycle? 这可能会创建保留周期吗?

AND

the current class holds a strong reference to viewControllerToDismiss and there is a code which looks like: 当前类拥有对viewControllerToDismiss的强引用,并且有一个代码如下:

[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{

   [self performSomeAction];
}

is this a retain cycle? 这是一个保留周期吗?

First, you have not declared a thread . 首先,您尚未声明一个主题 It's a queue, that's something different. 这是一个队列,这是不同的东西。 (Fortunately, as working directly with threads is a pain.) (幸运的是,直接使用线程是一件痛苦的事。)

You are dispatching a block into the queue. 您正在将一个块分派到队列中。 The block retains self and the queue retains the block, which means you do have a retain cycle, since the queue, being a strong property, is retained by self : 该块保留self并且队列保留块,这意味着您确实有一个保留周期,因为队列是一个strong属性,由self保留:

self -> queue -> block -> self -> queue -> …

BUT the block should be short-lived, judging by the API. 但是,根据API判断,块应该是短暂的。 When the block is finished, it will get released from the queue, breaking the retain cycle. 块完成后,它将从队列中释放,打破保留周期。 So I would not worry about a case like this. 所以我不担心这样的情况。

Using self directly in blocks will create strong retain cycle. 直接在块中使用self将创建强大的保留周期。

To avoid retain cycle, please check below code 为避免保留周期,请检查以下代码

__weak YourViewController *weakSelf = self;
dispatch_async(self.databaseQueue, ^{
     if (weakSelf){
        YourViewController *strongSelf = weakSelf;
        [strongSelf.dao deleteRetries];
      }
    });

For more info visit this link Working with blocks 有关更多信息,请访问此链接使用块

It is merely a strong reference to self that is eliminated automatically when the block finishes running and GCD releases the block. 它只是对self的强引用,当块完成运行并且GCD释放块时自动消除。 Note, this is a strong reference between the queue object itself, the block, and self , but not to databaseQueue . 注意,这是队列对象本身,块和self之间的强引用,而不是databaseQueue Eg even if databaseQueue was some local reference that had fallen out of scope after you dispatched but before it ran, you'd still have a strong reference between the queue object, the block, and self . 例如,即使在调度之后但在运行之前, databaseQueue是一些超出范围的本地引用,您仍然在队列对象,块和self之间有一个强引用。

If you don't want that strong reference at all, use weakSelf pattern: 如果您根本不想要强引用,请使用weakSelf模式:

typeof(self) __weak weakSelf = self;
dispatch_async(self.databaseQueue, ^{
    [weakSelf.dao deleteRetries];
});

You asked: 您询问:

Please could you elaborate more on "Note, this is a strong reference between the queue object itself, the block, and self, but not to databaseQueue"? 请你详细说明一下“注意,这是队列对象本身,块和自身之间的强引用,而不是databaseQueue”?

Consider: 考虑:

- (void)runManyTasks {
    dispatch_queue_t queue = dispatch_queue_create("com.domain.app.foo", 0);

    for (NSInteger i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            [self doSomething];
        });
    }
}

- (void)doSomething {
    [NSThread sleepForTimeInterval:1];
}

Even though I have no references in my code to that local variable, queue , after runManyTasks finishes, if I call runManyTasks , GCD will keep its own strong reference to the actual underlying queue object until all tasks finish, and the queue will keep copies of those blocks until they finish running, and those blocks will maintain a strong reference to self until GCD finishes with all of them (roughly 10 seconds, in this example). 即使我的代码中没有引用该局部变量, queue ,在runManyTasks完成后,如果我调用runManyTasks ,GCD将保留自己对实际底层队列对象的强引用,直到所有任务完成,并且队列将保留副本这些块直到它们完成运行,并且这些块将保持对self的强烈引用,直到GCD完成所有这些(在此示例中大约10秒)。


You go on to edit your question and ask: 您继续编辑您的问题并询问:

the current class holds a strong reference to viewControllerToDismiss and there is a code which looks like: 当前类拥有对viewControllerToDismiss的强引用,并且有一个代码如下:

 [viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{ [self performSomeAction]; } 

is this a retain cycle? 这是一个保留周期吗?

For all practical considerations, no. 出于所有实际考虑,没有。 That block is released as soon as the dismissal animation is done, so you generally wouldn't complicate your code with weakSelf pattern here. 一旦解雇动画完成,该块就会被释放,因此您通常不会在此处使用weakSelf模式使代码复杂化。 In fact, that view controller isn't dismissed until the animation finishes, anyway, so there's absolutely nothing gained from weakSelf pattern (other than making code more convoluted). 事实上,在动画结束之前,视图控制器不会被解雇,所以绝对没有从weakSelf模式中获得任何东西(除了使代码更复杂)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM