保留对 dispatch_queue 的强引用的循环
Retain cycle with strong reference to dispatch_queue
在 class 中,我声明了一个线程:
@property (nonatomic, strong) dispatch_queue_t databaseQueue;
然后我执行此线程的操作,例如
dispatch_async(self.databaseQueue, ^{
[self.dao deleteRetries];
});
这可能会创建一个保留周期吗?
AND
当前的 class 持有对 viewControllerToDismiss
的强引用,并且有一个代码如下所示:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
这是一个保留周期吗?
首先,你还没有声明一个线程。这是一个队列,这是不同的东西。 (幸运的是,因为直接使用线程很痛苦。)
您正在将一个块分派到队列中。该块保留 self
并且队列保留该块,这意味着您 do 有一个保留周期,因为队列是 strong
属性 , 由 self
:
保留
self -> queue -> block -> self -> queue -> …
但是根据 API 判断,该区块应该是短暂的。当块完成时,它将从队列中释放,从而打破保留循环。所以我不会担心这样的情况。
直接在块中使用 self 将创建强大的保留循环。
为了避免循环引用,请检查下面的代码
__weak YourViewController *weakSelf = self;
dispatch_async(self.databaseQueue, ^{
if (weakSelf){
YourViewController *strongSelf = weakSelf;
[strongSelf.dao deleteRetries];
}
});
有关详细信息,请访问此 link Working with blocks
它只是对 self
的强引用,当块完成 运行 并且 GCD 释放块时自动消除。请注意,这是队列对象本身、块和 self
之间的强引用,而不是 databaseQueue
。例如。即使 databaseQueue
是一些本地引用,在您发送之后但在发送之前超出范围 运行,您仍然可以在队列对象、块和 [=13= 之间拥有强引用].
如果你根本不需要强引用,请使用 weakSelf
模式:
typeof(self) __weak weakSelf = self;
dispatch_async(self.databaseQueue, ^{
[weakSelf.dao deleteRetries];
});
你问过:
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"?
考虑:
- (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];
}
即使我的代码中没有引用那个局部变量,queue
,在 runManyTasks
完成后,如果我调用 runManyTasks
,GCD 将保留它自己的强引用实际的底层队列对象,直到所有任务完成,队列将保留这些块的副本,直到它们完成 运行,并且这些块将保持对 self
的强引用,直到 GCD 完成所有这些块(大约 10 秒,在这个例子中)。
您继续编辑您的问题并提问:
the current class holds a strong reference to viewControllerToDismiss
and there is a code which looks like:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
is this a retain cycle?
出于所有实际考虑,不。一旦解雇动画完成,该块就会被释放,因此您通常不会在此处使用 weakSelf
模式使您的代码复杂化。事实上,无论如何,该视图控制器在动画完成之前不会被关闭,所以 weakSelf
模式绝对没有任何好处(除了使代码更复杂)。
在 class 中,我声明了一个线程:
@property (nonatomic, strong) dispatch_queue_t databaseQueue;
然后我执行此线程的操作,例如
dispatch_async(self.databaseQueue, ^{
[self.dao deleteRetries];
});
这可能会创建一个保留周期吗?
AND
当前的 class 持有对 viewControllerToDismiss
的强引用,并且有一个代码如下所示:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
这是一个保留周期吗?
首先,你还没有声明一个线程。这是一个队列,这是不同的东西。 (幸运的是,因为直接使用线程很痛苦。)
您正在将一个块分派到队列中。该块保留 self
并且队列保留该块,这意味着您 do 有一个保留周期,因为队列是 strong
属性 , 由 self
:
self -> queue -> block -> self -> queue -> …
但是根据 API 判断,该区块应该是短暂的。当块完成时,它将从队列中释放,从而打破保留循环。所以我不会担心这样的情况。
直接在块中使用 self 将创建强大的保留循环。
为了避免循环引用,请检查下面的代码
__weak YourViewController *weakSelf = self;
dispatch_async(self.databaseQueue, ^{
if (weakSelf){
YourViewController *strongSelf = weakSelf;
[strongSelf.dao deleteRetries];
}
});
有关详细信息,请访问此 link Working with blocks
它只是对 self
的强引用,当块完成 运行 并且 GCD 释放块时自动消除。请注意,这是队列对象本身、块和 self
之间的强引用,而不是 databaseQueue
。例如。即使 databaseQueue
是一些本地引用,在您发送之后但在发送之前超出范围 运行,您仍然可以在队列对象、块和 [=13= 之间拥有强引用].
如果你根本不需要强引用,请使用 weakSelf
模式:
typeof(self) __weak weakSelf = self;
dispatch_async(self.databaseQueue, ^{
[weakSelf.dao deleteRetries];
});
你问过:
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"?
考虑:
- (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];
}
即使我的代码中没有引用那个局部变量,queue
,在 runManyTasks
完成后,如果我调用 runManyTasks
,GCD 将保留它自己的强引用实际的底层队列对象,直到所有任务完成,队列将保留这些块的副本,直到它们完成 运行,并且这些块将保持对 self
的强引用,直到 GCD 完成所有这些块(大约 10 秒,在这个例子中)。
您继续编辑您的问题并提问:
the current class holds a strong reference to
viewControllerToDismiss
and there is a code which looks like:[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{ [self performSomeAction]; }
is this a retain cycle?
出于所有实际考虑,不。一旦解雇动画完成,该块就会被释放,因此您通常不会在此处使用 weakSelf
模式使您的代码复杂化。事实上,无论如何,该视图控制器在动画完成之前不会被关闭,所以 weakSelf
模式绝对没有任何好处(除了使代码更复杂)。