Swift iOS问题:已取消并置为Nil的DispatchWorkItem仍在运行
使用GCD DispatchWorkItem跟踪Firebase数据发送状态
我来分享一个实用的方案,用GCD的DispatchWorkItem来跟踪发送到Firebase的数据状态,主要用来处理请求未及时响应时的兜底逻辑:
第一步:声明类属性
先在你的Firebase管理类里声明两个DispatchWorkItem类型的属性(这里重点讲你提到的errorTask,另一个可以根据你的扩展需求定义):
class FirebaseDataManager { // 处理请求异常/超时的兜底任务 private var errorTask: DispatchWorkItem? // 持有Firebase请求任务,用于后续取消操作 private var firebaseTask: Task<Void, Error>? }
第二步:初始化并配置errorTask
当准备发送数据时,我们要初始化errorTask,它的核心逻辑是取消Firebase请求、清理资源并给出提示。同时通过asyncAfter设置一个极短的定时器,只要请求没有在定时器触发前完成,这个任务就会自动执行:
func sendDataToFirebase(with data: [String: Any]) { // 先清理之前可能残留的errorTask,避免干扰新请求 errorTask?.cancel() // 初始化errorTask errorTask = DispatchWorkItem { [weak self] in // 取消Firebase请求任务 self?.firebaseTask?.cancel() self?.firebaseTask = nil print("errorTask fired") } // 设置定时器:0.0000000001秒后触发,只要没提前取消就执行errorTask DispatchQueue.global().asyncAfter(deadline: .now() + 0.0000000001, execute: errorTask!) // 发起Firebase数据请求 firebaseTask = Task { try await Firestore.firestore().collection("your_target_collection").addDocument(data: data) // 请求成功完成,立即取消errorTask errorTask?.cancel() errorTask = nil print("数据发送成功") } // 监听任务失败情况 Task { do { try await firebaseTask?.value } catch { errorTask?.cancel() errorTask = nil print("数据发送失败: \(error.localizedDescription)") } } }
关键细节说明
- 定时器的作用:这个极短的定时器其实是利用了
DispatchWorkItem的可取消特性——如果Firebase请求能正常回调(不管成功还是失败),我们都会立即取消errorTask,它就不会执行;只有当请求挂起、迟迟没有响应时,定时器才会触发兜底逻辑。 - 循环引用避免:一定要在
DispatchWorkItem的闭包里用[weak self],不然会导致FirebaseDataManager无法被正常释放,造成内存泄漏。 - 前置清理:每次发送新数据前取消旧的
errorTask,是为了防止旧请求的兜底任务在新请求发起后误触发。
内容的提问来源于stack exchange,提问作者Lance Samaria
相关产品推荐
相关产品推荐

