强引用 dispatch_queue 的保留周期

pra*_*ash 5 objective-c grand-central-dispatch ios

在课堂上,我声明了一个线程,如:

@property (nonatomic, strong) dispatch_queue_t databaseQueue;

然后我执行这个线程的操作

dispatch_async(self.databaseQueue, ^{
        [self.dao deleteRetries];
    });
Run Code Online (Sandbox Code Playgroud)

这可能会创建一个保留周期吗?

当前类拥有对的强引用,viewControllerToDismiss并且有一段代码如下:

[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{

   [self performSomeAction];
}
Run Code Online (Sandbox Code Playgroud)

这是一个保留周期吗?

Rob*_*Rob 3

它只是一个强引用,self当块完成运行并且 GCD 释放块时会自动消除。请注意,这是队列对象本身、块和 之间的强引用self,但不是 to 之间的强引用databaseQueue。例如,即使databaseQueue某些本地引用在您分派之后但在运行之前超出了范围,您仍然在队列对象、块和self.

如果您根本不需要强引用,请使用weakSelf模式:

typeof(self) __weak weakSelf = self;
dispatch_async(self.databaseQueue, ^{
    [weakSelf.dao deleteRetries];
});
Run Code Online (Sandbox Code Playgroud)

你问:

请您详细说明一下“注意,这是队列对象本身、块和自身之间的强引用,但不是数据库队列”?

考虑:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

即使我的代码中没有对该局部变量的引用,queuerunManyTasks完成后,如果我调用runManyTasks,GCD 将保留其对实际底层队列对象的强引用,直到所有任务完成,并且队列将保留这些块的副本,直到它们完成运行,并且这些块将保持强引用,self直到 GCD 完成所有块(在本例中大约 10 秒)。


您继续编辑您的问题并询问:

当前类拥有强引用,viewControllerToDismiss并且有一个代码如下所示:

[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
     [self performSomeAction];
 }
Run Code Online (Sandbox Code Playgroud)

这是一个保留周期吗?

出于所有实际考虑,答案是否定的。一旦解雇动画完成,该块就会被释放,因此您通常不会weakSelf在此处使用模式使代码复杂化。事实上,无论如何,在动画完成之前该视图控制器都不会被关闭,因此从weakSelf模式中绝对没有任何好处(除了使代码更加复杂之外)。