Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
/OperationPlusPublic archive

NSOperation's missing pieces

License

NotificationsYou must be signed in to change notification settings

ChimeHQ/OperationPlus

Build StatusPlatforms

OperationPlus

OperationPlus is a set ofNSOperation subclasses and extensions onNSOperation/NSOperationQueue. Its goal is to fill in the API's missing pieces. You don't need to learn anything new to use it.

NSOperation has been around for a long time, and there are now two potential first-party alternatives, Combine and Swift concurrency. OperationPlus includes some facilities to help Combine and NSOperation interoperate conveniently.

Integration

Swift Package Manager:

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

NSOperation Subclasses

  • BaseOperation: provides core functionality for easierNSOperation subclassing
  • AsyncOperation: convenience wrapper aroundBaseOperation for async support
  • AsyncBlockOperation: convenience class for inline async support
  • (Async)ProducerOperation: produces an output
  • (Async)ConsumerOperation: accepts an input from aProducerOperation
  • (Async)ConsumerProducerOperation: accepts an input from aProducerOperation and also produces an output

BaseOperation

This is a simpleNSOperation subclass built for easier extensibility. It features:

  • Thread-safety
  • Timeout support
  • Easier cancellation handling
  • Stricter state checking
  • Built-in asynchrous support
  • Straight-foward customization
leta=BaseOperation(timeout:5.0)// NSOperation will happily allow you do this even// if `a` has finished. `BaseOperation` will not.a.addDependency(another)// ...publicoverridefunc main(){    // This will return true if your operation is cancelled, timed out,    // or prematurely finished. ProducerOperation subclass state will be    // handled correctly as well.ifself.checkForCancellation(){return}}// ...

AsyncOperation

ABaseOperation subclass that can be used for your asynchronous operations. These are any operations that need to extend their lifetime past themain method.

import Foundationimport OperationPlusclassMyAsyncOperation:AsyncOperation{publicoverridefunc main(){DispatchQueue.global().async{ifself.checkForCancellation(){return}            // do stuffself.finish()}}}

There's also nothing special about this class at all -- it's there just for convenience. If you want, you can just subclassBaseOperation directly and override one method.

import Foundationimport OperationPlusclassMyAsyncOperation:BaseOperation{overrideopenvarisAsynchronous:Bool{returntrue}}

ProducerOperation

ABaseOperation subclass that yields a value. Includes a completion handler to access the value.

import Foundationimport OperationPlusclassMyValueOperation:ProducerOperation<Int>{publicoverridefunc main(){        // do your computationself.finish(with:42)}}// ...letop=MyValueOperation()op.resultCompletionBlock={(value)in    // use value here}

AsyncProducerOperation

A variant ofProducerOperation that may produce a value after themain method has completed executing.

import Foundationimport OperationPlusclassMyAsyncOperation:AsyncProducerOperation<Int>{publicoverridefunc main(){DispatchQueue.global().async{ifself.checkForCancellation(){return}            // do stuffself.finish(with:42)}}}

ConsumerOperation andAsyncConsumerOperation

ABaseOperation sublass that accepts the input of aProducerOperation.

import Foundationimport OperationPlusclassMyConsumerOperation:ConsumerOperation<Int>{overridefunc main(){guardlet value= producerValueelse{            // handle failure in some way}}overridefunc main(with value:Int){        // make use of value here, or automatically        // fail if it wasn't successfully produced}}letop=MyConsumerOperation(producerOp: myIntProducerOperation)

AsyncBlockOperation

A play onNSBlockOperation, but makes it possible to support asynchronous completion without making anOperation subclass. Great for quick, inline work.

letop=AsyncBlockOperation{(completionBlock)inDispatchQueue.global().async{        // do some async work here, just be certain to call        // the completionBlock when donecompletionBlock()}}

NSOperation/NSOperationQueue Extensions

Queue creation conveniences:

leta=OperationQueue(name:"myqueue")letb=OperationQueue(name:"myqueue", maxConcurrentOperations:1)letc=OperationQueue.serialQueue()letd=OperationQueue.serialQueue(named:"myqueue")

Enforcing runtime constraints on queue execution:

OperationQueue.preconditionMain()OperationQueue.preconditionNotMain()

Consise dependencies:

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

Queueing work when a queue's current operations are complete:

queue.currentOperationsFinished{print("all pending ops done")}

Convenient inline functions:

queue.addAsyncOperation{(completionHandler)inDispatchQueue.global().async{        // do some async workcompletionHandler()}}

Async integration:

queue.addOperation{awaitasyncFunction1()awaitasyncFunction2()}letvalue=tryawait queue.addResultOperation{tryawaitasyncValue()}

Delays:

queue.addOperation(op, afterDelay:5.0)queue.addOperation(afterDelay:5.0){  // work}

Combine Integration

PublisherOperation

ThisProducerOperation subclass takes a publisher. When executed, it creates a subscription and outputs the results.

op.publisher() // AnyPublisher<Void, Never>producerOp.outputPublisher() // AnyPublisher<Output, Never>
publisher.operation() // PublisherOperationpublisher.execute(on: queue) // subscribes and executes chain on queue and returns a publisher for result

XCTest Support

OperationTestingPlus is an optional micro-framework to help make your XCTest-based tests a little nicer. When using Carthage, it is built as a static framework to help ease integration with your testing targets.

FulfillExpectationOperation

A simple NSOperation that will fulfill anXCTestExpectation when complete. Super-useful when used with dependencies on your other operations.

NeverFinishingOperation

A great way to test out your Operations' timeout behaviors.

OperationExpectation

AnXCTestExpectation sublass to make testing async operations a little more XCTest-like.

letop=NeverFinishingOperation()letexpectation=OperationExpectation(operation: op)expectation.isInverted=truewait(for:[expectation], timeout:1.0)

Suggestions or Feedback

We'd love to hear from you! Get in touch via an issue or pull request.

Please note that this project is released with aContributor Code of Conduct. By participating in this project you agree to abide by its terms.


[8]ページ先頭

©2009-2025 Movatter.jp