该功能应该重新安排工作项的执行时间:
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
可以为空吗?id
时,workItem
中的workItem
可以为空吗?还是由范围let id = self.id
保留了?
isDoing
对象已经被释放,那么workItem
内部的workItem
是否已经被释放?换句话说,当释放MyClass
对象时,调度的workItem
会发生什么?答案 0 :(得分:1)
不确定您的意思。您不会在任何地方淘汰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
}