OperationPlus 是一组 NSOperation
的子类,以及对 NSOperation
/NSOperationQueue
的扩展。 它的目标是填补 API 中缺失的部分。 你不需要学习任何新东西就可以使用它。
NSOperation 已经存在很长时间了,现在有两种潜在的官方替代方案:Combine 和 Swift 并发。 OperationPlus 包含一些工具,可以方便地帮助 Combine 和 NSOperation 互操作。
Swift Package Manager
dependencies: [
.package(url: "https://github.com/ChimeHQ/OperationPlus.git")
]
BaseOperation
: 为更轻松地创建 NSOperation
子类提供核心功能AsyncOperation
: 用于异步支持的 BaseOperation
的便捷封装AsyncBlockOperation
: 用于内联异步支持的便捷类(Async)ProducerOperation
: 产生一个输出(Async)ConsumerOperation
: 接受来自 ProducerOperation
的输入(Async)ConsumerProducerOperation
: 接受来自 ProducerOperation
的输入,并产生一个输出BaseOperation
这是一个简单的 NSOperation
子类,专为更轻松的扩展而构建。 它具有以下特点:
let a = BaseOperation(timeout: 5.0)
// NSOperation will happily allow you do this even
// if `a` has finished. `BaseOperation` will not.
a.addDependency(another)
// ...
public override func main() {
// This will return true if your operation is cancelled, timed out,
// or prematurely finished. ProducerOperation subclass state will be
// handled correctly as well.
if self.checkForCancellation() {
return
}
}
// ...
AsyncOperation
一个 BaseOperation
子类,可用于你的异步操作。 这些是任何需要将其生命周期延长到 main
方法之后的操作。
import Foundation
import OperationPlus
class MyAsyncOperation: AsyncOperation {
public override func main() {
DispatchQueue.global().async {
if self.checkForCancellation() {
return
}
// do stuff
self.finish()
}
}
}
这个类没有什么特别之处 —— 它只是为了方便而存在。 如果你愿意,你可以直接继承 BaseOperation
并覆盖一个方法。
import Foundation
import OperationPlus
class MyAsyncOperation: BaseOperation {
override open var isAsynchronous: Bool {
return true
}
}
ProducerOperation
一个产生值的 BaseOperation
子类。 包括一个完成处理程序来访问该值。
import Foundation
import OperationPlus
class MyValueOperation: ProducerOperation<Int> {
public override func main() {
// do your computation
self.finish(with: 42)
}
}
// ...
let op = MyValueOperation()
op.resultCompletionBlock = { (value) in
// use value here
}
AsyncProducerOperation
一个 ProducerOperation
的变体,可以在 main
方法执行完成后产生一个值。
import Foundation
import OperationPlus
class MyAsyncOperation: AsyncProducerOperation<Int> {
public override func main() {
DispatchQueue.global().async {
if self.checkForCancellation() {
return
}
// do stuff
self.finish(with: 42)
}
}
}
ConsumerOperation 和 AsyncConsumerOperation
一个接受 ProducerOperation
输入的 BaseOperation
子类。
import Foundation
import OperationPlus
class MyConsumerOperation: ConsumerOperation<Int> {
override func main() {
guard let value = producerValue else {
// handle failure in some way
}
}
override func main(with value: Int) {
// make use of value here, or automatically
// fail if it wasn't successfully produced
}
}
let op = MyConsumerOperation(producerOp: myIntProducerOperation)
AsyncBlockOperation
一个关于 NSBlockOperation
的变体,但可以支持异步完成,而无需创建 Operation
子类。 非常适合快速的内联工作。
let op = AsyncBlockOperation { (completionBlock) in
DispatchQueue.global().async {
// do some async work here, just be certain to call
// the completionBlock when done
completionBlock()
}
}
队列创建的便利方法
let a = OperationQueue(name: "myqueue")
let b = OperationQueue(name: "myqueue", maxConcurrentOperations: 1)
let c = OperationQueue.serialQueue()
let d = OperationQueue.serialQueue(named: "myqueue")
在队列执行上强制执行运行时约束
OperationQueue.preconditionMain()
OperationQueue.preconditionNotMain()
简洁的依赖关系
queue.addOperation(op, dependency: opA)
queue.addOperation(op, dependencies: [opA, opB])
queue.addOperation(op, dependencies: Set([opA, opB]))
op.addDependencies([opA, opB])
op.addDependencies(Set([opA, opB]))
当队列的当前操作完成时,排队工作
queue.currentOperationsFinished {
print("all pending ops done")
}
方便的内联函数
queue.addAsyncOperation { (completionHandler) in
DispatchQueue.global().async {
// do some async work
completionHandler()
}
}
异步集成
queue.addOperation {
await asyncFunction1()
await asyncFunction2()
}
let value = try await queue.addResultOperation {
try await asyncValue()
}
延迟
queue.addOperation(op, afterDelay: 5.0)
queue.addOperation(afterDelay: 5.0) {
// work
}
PublisherOperation
这个 ProducerOperation
子类接受一个 publisher。 当执行时,它创建一个订阅并输出结果。
op.publisher() // AnyPublisher<Void, Never>
producerOp.outputPublisher() // AnyPublisher<Output, Never>
publisher.operation() // PublisherOperation
publisher.execute(on: queue) // subscribes and executes chain on queue and returns a publisher for result
OperationTestingPlus 是一个可选的微框架,可以帮助你的基于 XCTest 的测试更加友好。 当使用 Carthage 时,它被构建为一个静态框架,以帮助简化与你的测试目标的集成。
FulfillExpectationOperation
一个简单的 NSOperation,它将在完成时满足 XCTestExpectation
。 当与你的其他操作的依赖项一起使用时,非常有用。
NeverFinishingOperation
测试 Operations 超时行为的好方法。
OperationExpectation
一个 XCTestExpectation
子类,使测试异步操作更像 XCTest。
let op = NeverFinishingOperation()
let expectation = OperationExpectation(operation: op)
expectation.isInverted = true
wait(for: [expectation], timeout: 1.0)
我们很乐意听取你的意见! 通过 issue 或 pull request 与我们联系。
请注意,此项目以 贡献者行为准则 发布。 通过参与此项目,你同意遵守其条款。