每天了解一点不一样的 Swift 小知识

代码截图

image.png

小笔记

这段代码在说什么

代码截图里,首先使用 DispatchWorkItem 创建了一个待执行任务,然后我们将该任务放在主队列中,声明该任务会在 1 秒后执行。最后一句代码不是必要的,它表示立即取消执行中的任务。

如果之前的代码执行正常的话,任务在执行完毕后就不会占用任何系统资源,但在某些情况下,例如第二句代码执行了 1 分钟还是没结束,这意味着主线程极有可能被阻塞了 1 分钟,为了不影响用户体验,我们极有可能会考虑停止当前任务。所以会需要使用 cancel 方法。写在这里只是为了表明我们可以在需要的时刻,调用并停止对应的任务。

DispatchWorkItem 是什么

早期的 GCD 可能会给使用者留下这么一个印象:一旦安排了一个任务就无法取消,需要操作 Operation 的 API 来取消任务。 如果有点忘了,我们用下面一段示例代码来回味一下,为了增加些许怀旧情结,这里的代码是用 objective-c 写的:

NSOperationQueue* queue = [NSOperationQueue new];
queue.maxConcurrentOperationCount = 1; // make it a serial queue
...
[queue addOperationWithBlock:...]; // add operations to it
...
// Cleanup logic. At this point _do not_ add more operations to the queue
queue.suspended = YES; // halts execution of the queue
[queue cancelAllOperations]; // notify all pending operations to terminate
queue.suspended = NO; // let it go.
queue=nil; // discard object

不过这一现象在 iOS 8 之后发生了变化,Apple 提出了 DispatchWorkItem 这个概念和相关 API。

同样的功能,使用 DispatchWorkItem 后,我们只需要像代码截图里一样:调用 DispatchWorkItem 的实例方法 cancel 即可,这避免了一堆对 NSOperationQueue 的冗余操作。

workItem.cancel()

回到 DispatchWorkItem 上,它到底是个什么呢?通俗的来说,DispatchWorkItem 就是 GCD 里面常说的一段待执行的任务,更直白一点,它本质只是一个等待执行的代码块而已,可以在任意一个队列上被调用。

DispatchWorkItem 怎么用

DispatchWorkItem的初始化方法可以配置 Qos 和 DispatchWorkItemFlags,但是这两个参数都有默认参数,所以也可以只传入一个闭包也可以。

let workItem = DispatchWorkItem {
// Do something
}

除了代码截图里的 cancel 方法外,常见的方法还有:

  • perform() 方法:在队列中执行当前 DispatchWorkItem 的任务。
  • notify(queue:, execute:) 方法:在当前任务完成后,通知其他队列中的 DispatchWorkItem 实例。
  • wait() 方法:DispatchWorkItem 实例会阻塞当前线程直到任务完成。