Build Status Platforms

OperationPlus

OperationPlus 是一组 NSOperation 的子类,以及对 NSOperation/NSOperationQueue 的扩展。 它的目标是填补 API 中缺失的部分。 你不需要学习任何新东西就可以使用它。

NSOperation 已经存在很长时间了,现在有两种潜在的官方替代方案:Combine 和 Swift 并发。 OperationPlus 包含一些工具,可以方便地帮助 Combine 和 NSOperation 互操作。

集成

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/ChimeHQ/OperationPlus.git")
]

NSOperation 子类

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

ConsumerOperationAsyncConsumerOperation

一个接受 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()
    }
}

NSOperation/NSOperationQueue 扩展

队列创建的便利方法

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
}

Combine 集成

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

XCTest 支持

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 与我们联系。

请注意,此项目以 贡献者行为准则 发布。 通过参与此项目,你同意遵守其条款。