这个函数应该重新安排工作项的执行:
class MyClass {
var id: String?
var workItem: DispatchWorkItem?
var isDoing = false
func myFunction() {
guard let id = self.id else { return }
isDoing = true
NotificationCenter.default.post(name: MyNotification, object: nil, userInfo: ["id": id])
workItem?.cancel()
workItem = DispatchWorkItem {
self.isDoing = false
NotificationCenter.default.post(name: MyNotification, object: nil, userInfo: ["id": id])
}
if let workItem = workItem {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(10), execute: workItem)
}
}
}
它在开发中运行良好,但设计似乎很可疑,所以我问了一些基本问题:
- 如果在队列尝试执行
workItem
之前调用workItem?.cancel()
,workItem
是否可以为 nil?< - 在执行
workItem
时,workItem
中的id
是否可以为 nil,或者它是否由作用域let id = self.编号
? workItem
中的isDoing
是否已经在执行workItem
时被释放,如果MyClass
对象已被释放?换句话说,当MyClass
对象被释放时,调度的workItem
会发生什么?
最佳答案
不太清楚你的意思。您不会在任何地方取消
workItem
。不,它不能是
nil
,因为您正在使用局部变量 -self.id
的副本。通过使用guard
,您可以确保局部变量id
不为 nil,并且闭包保持对捕获值的强引用(默认情况下),因此它不会被释放。isDoing
是MyClass
的实例变量,因此在释放MyClass
实例之前不能释放它。问题是,在您的情况下MyClass
无法被释放,因为您正在查看一个强引用循环。默认情况下,闭包保持对捕获值的强引用,并且您正在捕获self
。由于self
保持对workItem
的强引用,这反过来又保持对捕获self
的闭包的强引用,因此引用周期。
通常,当捕获 self
时,您使用捕获列表来处理对 self
的弱引用,并检查它是否尚未被释放
workItem = DispatchWorkItem { [weak self] in
guard let strongSelf = self else { return }
// do stuff with strongSelf
}
关于ios - 如何防止在 GCD 中释放对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51023959/