ios - 如何防止在 GCD 中释放对象?

标签 ios swift grand-central-dispatch dispatchworkitem

这个函数应该重新安排工作项的执行:

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)
        }
    }
}

它在开发中运行良好,但设计似乎很可疑,所以我问了一些基本问题:

  1. 如果在队列尝试执行 workItem 之前调用 workItem?.cancel()workItem 是否可以为 nil?<
  2. 在执行 workItem 时,workItem 中的 id 是否可以为 nil,或者它是否由作用域 let id = self.编号?
  3. workItem 中的 isDoing 是否已经在执行 workItem 时被释放,如果 MyClass 对象已被释放?换句话说,当 MyClass 对象被释放时,调度的 workItem 会发生什么?

最佳答案

  1. 不太清楚你的意思。您不会在任何地方取消 workItem

  2. 不,它不能是 nil,因为您正在使用局部变量 - self.id 的副本。通过使用 guard,您可以确保局部变量 id 不为 nil,并且闭包保持对捕获值的强引用(默认情况下),因此它不会被释放。

  3. isDoingMyClass 的实例变量,因此在释放 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/

相关文章:

iphone - 属性(property)失去值(value)(长但容易理解)

ios - Objective-C 等待异步操作和排队完成处理程序

objective-c - 奇怪的dispatch_async内存行为

ios - Firebase iOS Swift 日期和时间

ios - 如何使用 Swift 在 Tableview Cell 中添加 UITableview

ios - 无法从 UITableViewCell 中删除标签

generics - 无法在 Swift 中使用函数类型作为泛型类型约束

ios - 如何在自定义区域中创建 CKRecord 而无需指定记录名称?

ios - 如何从 Appdelegate 打开 Viewcontroller?

ios - GCD NSURLSession completionHandler block 返回值 null