在课堂上,我宣布了一个如下话题:
@property (nonatomic, strong) dispatch_queue_t databaseQueue;
然后我执行这个线程的操作,如
dispatch_async(self.databaseQueue, ^{
[self.dao deleteRetries];
});
这可能会创建一个保留周期吗?
和
当前类对viewControllerToDismiss
有强烈的引用,并且有一个代码如下:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
这是一个保留周期吗?
答案 0 :(得分:2)
首先,您尚未声明线程。这是一个队列,这是不同的东西。 (幸运的是,直接使用线程是一种痛苦。)
您正在将一个块分派到队列中。该块保留self
并且队列保留该块,这意味着您做具有保留周期,因为队列是strong
属性,由{{1保留}}:
self
但是,根据API判断,块应该是短暂的。块完成后,它将从队列中释放,打破保留周期。所以我不担心这样的情况。
答案 1 :(得分:2)
直接在块中使用self会产生强大的保留周期。
为避免保留周期,请查看以下代码
__weak YourViewController *weakSelf = self;
dispatch_async(self.databaseQueue, ^{
if (weakSelf){
YourViewController *strongSelf = weakSelf;
[strongSelf.dao deleteRetries];
}
});
有关详细信息,请访问此链接Working with blocks
答案 2 :(得分:2)
它只是对self
的强引用,当块完成运行并且GCD释放块时会自动消除。请注意,这是队列对象本身,块和self
之间的强引用,而不是databaseQueue
。例如。即使databaseQueue
是在您调度之后但在运行之前已超出范围的某些本地引用,您仍然在队列对象,块和self
之间有一个强引用。
如果您根本不想要强引用,请使用weakSelf
pattern:
typeof(self) __weak weakSelf = self;
dispatch_async(self.databaseQueue, ^{
[weakSelf.dao deleteRetries];
});
你问:
请你详细说明一下“注意,这是队列对象本身,块和self之间的强引用,而不是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秒,在此例子)。
您继续编辑您的问题并询问:
当前类对
viewControllerToDismiss
有强烈的引用,并且有一个代码如下:[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{ [self performSomeAction]; }
这是一个保留周期吗?
出于所有实际考虑,没有。一旦解雇动画完成,该块就会被释放,因此您通常不会在此处使用weakSelf
模式使代码复杂化。实际上,在动画结束之前,视图控制器不会被解雇,所以绝对没有从weakSelf
模式中获得任何东西(除了使代码更复杂)。