Queuer 是一个队列管理器,构建于 OperationQueue 和 Dispatch (又名 GCD) 之上。 它允许您轻松创建任何异步和同步任务,所有这些都由队列管理,只需几行代码即可。
以下是所有功能的列表
| Swift | Queuer | iOS | macOS | macCatalyst | tvOS | watchOS | visionOS | Linux |
|---|---|---|---|---|---|---|---|---|
| 3.1...3.2 | 1.0.0...1.1.0 | 8.0+ | 10.10+ | 9.0+ | 2.0+ | ✅ | ||
| 4.0 | 1.3.0 | 8.0+ | 10.10+ | 9.0+ | 2.0+ | ✅ | ||
| 4.1 | 1.3.1...1.3.2 | 8.0+ | 10.10+ | 9.0+ | 2.0+ | ✅ | ||
| 4.2 | 2.0.0...2.0.1 | 8.0+ | 10.10+ | 9.0+ | 3.0+ | ✅ | ||
| 5.0...5.10 | 2.1.0...2.2.0 | 8.0+ | 10.10+ | 9.0+ | 3.0+ | ✅ | ||
| 5.9...5.10 | 3.0.0 | 12.0+ | 10.13+ | 13.0+ | 12.0+ | 4.0+ | 1.0+ | ✅ |
请参阅 Requirements 部分以检查 Swift、Queuer 和 OS 版本。
在您的 Package.swift Swift Package Manager 清单中,将以下依赖项添加到您的 dependencies 参数
.package(url: "https://github.com/FabrizioBrancati/Queuer.git", from: "3.0.0"),
将依赖项添加到您在清单中声明的任何目标
.target(
name: "MyTarget",
dependencies: [
.product(name: "Queuer", package: "Queuer"),
]
),
Queuer 提供了一个共享实例,您可以使用它将操作添加到中心化队列
Queuer.shared.addOperation(operation)
您还可以创建一个自定义队列
let queue = Queuer(name: "MyCustomQueue")
您甚至可以通过定义 maxConcurrentOperationCount 和 qualityOfService 属性来创建队列
let queue = Queuer(name: "MyCustomQueue", maxConcurrentOperationCount: Int.max, qualityOfService: .default)
您有三种方法可以添加 Operation 块。
直接在 queue(或 Queuer.shared)上
queue.addOperation {
/// Your task here
}
使用块创建一个 ConcurrentOperation
let concurrentOperation = ConcurrentOperation { _ in
/// Your task here
}
queue.addOperation(concurrentOperation)
注意
我们稍后会看到 ConcurrentOperation 的工作原理。
链式操作是相互添加依赖关系的 Operation。
它们遵循给定的数组顺序,例如: [A, B, C] = A -> B -> C -> completionBlock。
let concurrentOperationA = ConcurrentOperation { _ in
/// Your task A here
}
let concurrentOperationB = ConcurrentOperation { _ in
/// Your task B here
}
queue.addChainedOperations([concurrentOperationA, concurrentOperationB]) {
/// Your completion task here
}
您还可以在队列创建后添加一个 completionHandler,使用
queue.addCompletionHandler {
/// Your completion task here
}
组操作是处理一组带有完成处理程序的 Operation 的 Operation。
允许执行一组带有完成处理程序的 Operation,该完成处理程序将在所有操作完成后调用,例如: [A -> [[B & C & D] -> completionHandler] -> E] -> completionHandler。 它通常应与 Chained Opetation 一起使用。
let groupOperationA = GroupOperation(
[
ConcurrentOperation { _ in
/// Your task A here
},
ConcurrentOperation { _ in
/// Your task B here
}
]
)
let concurrentOperationC = ConcurrentOperation { _ in
/// Your task C here
}
queue.addChainedOperations([groupOperationA, concurrentOperationC]) {
/// Your completion task here
}
在这种情况下,输出将如下所示: [[A & B -> completionHandler] -> C] -> completionHandler。
有几种方法可以处理队列状态。
取消队列中的所有 Operation
queue.cancelAll()
暂停队列
queue.pause()
警告
通过调用 pause(),您不能确定每个 Operation 都会被暂停。 如果 Operation 已经启动,则在它是覆盖 pause() 函数的自定义 Operation 之前,它不会暂停。
恢复队列
queue.resume()
警告
要获得完整的 pause 和 resume 状态,您必须创建一个覆盖 pause() 和 resume() 函数的自定义 Operation。
等待直到所有 Operation 完成
queue.waitUntilAllOperationsAreFinished()
重要
此函数意味着队列将阻塞当前线程,直到所有 Operation 完成。
将队列的 maxConcurrentOperationCount 属性设置为 1 将确保一次只执行一个任务。
ConcurrentOperation 是一个被创建用于被子类化的类。 它允许同步和异步任务,具有暂停和恢复状态,可以轻松添加到队列,并且可以使用块创建。
您可以通过子类化来创建您的自定义 ConcurrentOperation。
您必须覆盖 execute() 函数,并在任务完成其工作以通知队列时,在其中调用 finish(success:) 函数。
为方便起见,它有一个带有完成块的 init 函数
let concurrentOperation = ConcurrentOperation { _ in
/// Your task here
}
concurrentOperation.addToQueue(queue)
一个 Operation 被传递给每个闭包,通过它您可以设置和处理重试功能。
默认情况下,重试功能被禁用,要启用它,只需将 success 属性设置为 false。 success 为 false 时,Operation 将重试,直到达到 maximumRetries 属性值。 为了让 Operation 知道何时一切正常,您必须将 success 设置为 true。
通过 currentAttempt,您可以知道 Operation 处于哪个尝试次数。
let concurrentOperation = ConcurrentOperation { operation in
/// Your task here
if /* Successful */ {
operation.success = true
} else {
operation.success = false
}
}
当您认为执行会成功时,您可以手动重试 Operation。
一个 Operation 被传递给每个闭包,通过它您可以设置和处理重试功能。
默认情况下,手动重试功能被禁用,要启用它,只需将 manualRetry 属性设置为 true,您必须在执行闭包之外执行此操作。 您还必须将 success 设置为 true 或 false,以让 Operation 知道何时一切正常,就像自动重试功能一样。
要让 Operation 重试您的执行闭包,您必须调用 retry() 函数。 确保至少调用 maximumRetries 次,如果您调用 retry() 的次数多于需要的次数,则没有问题,您的执行闭包将不会执行超过 maximumRetries 值的次数。
let concurrentOperation = ConcurrentOperation { operation in
/// Your task here
if /* Successful */ {
operation.success = true
} else {
operation.success = false
}
}
concurrentOperation.manualRetry = true
/// Later on your code
concurrentOperation.retry()
注意
如果未调用 retry() 函数,您可能会阻塞整个队列。
默认情况下,Operation 将在执行闭包完成时完成其工作。
这意味着,如果您的闭包中有一个异步任务,Operation 将在任务完成之前完成。
如果您想手动完成它,您可以将 manualFinish 属性设置为 true,并在任务完成时调用 finish(success:) 函数。
使用 success 参数将 finish(success:) 函数调用为 true 或 false,以让 Operation 知道任务是否成功。 如果您没有显式设置 success 参数,它将被设置为 true。
let concurrentOperation = ConcurrentOperation { operation in
/// Your asynchonous task here
}
concurrentOperation.manualFinish = true
/// Later on your code in your asynchronous task
concurrentOperation.finish(success: true)
注意
如果您不调用 finish(success:) 函数,您的队列将被阻塞,并且永远不会结束。
如果您想使用 async/await 任务,您需要将 manualFinish 设置为 true,以便完全控制 Operation 生命周期。
注意
阅读更多关于手动完成 Operation 的信息 这里。
let concurrentOperation = ConcurrentOperation { operation in
Task {
/// Your asynchonous task here
operation.finish(success: true) // or false
}
/// Your asynchonous task here
}
concurrentOperation.manualFinish = true
注意
如果您不将 manualFinish 设置为 true,您的 Operation 将在异步任务完成之前完成。
Scheduler 是一个结构体,它使用 GDC 的 DispatchSourceTimer 来创建一个定时器,该定时器可以使用指定的间隔和服务质量执行函数。
let schedule = Scheduler(deadline: .now(), repeating: .seconds(1)) {
/// Your task here
}
您甚至可以在没有处理程序的情况下创建一个 Scheduler,稍后再设置它
var schedule = Scheduler(deadline: .now(), repeating: .seconds(1))
schedule.setHandler {
/// Your task here
}
通过 timer 属性,您可以访问所有 DispatchSourceTimer 属性和函数,例如 cancel()
schedule.timer.cancel()
Semaphore 是一个结构体,它使用 GCD 的 DispatchSemaphore 在函数上创建一个信号量,并等待它完成其工作。
提示
建议在 Semaphore 创建和 wait() 调用之后立即使用 defer { semaphore.continue() }。
let semaphore = Semaphore()
semaphore.wait()
defer { semaphore.continue() }
/// Your task here
您甚至可以设置自定义超时,默认为 .distantFuture
semaphore.wait(DispatchTime(uptimeNanoseconds: 1_000_000_000))
如果在异步任务中使用它会更有用
let concurrentOperation = ConcurrentOperation {
/// Your task here
semaphore.continue()
}
concurrentOperation.addToQueue(queue)
semaphore.wait()
要查看 Queuer 最近版本中的更改,请参阅 CHANGELOG.md 文件。
请参阅 CONTRIBUTING.md 文件。
Queuer 在 MIT 许可证下可用。 有关更多信息,请参阅 LICENSE 文件。