Queuer
Queuer is a queue manager built on top of OperationQueue and Dispatch (aka GCD). It allows you to create asynchronous and synchronous tasks easily, all managed by a queue, with just a few lines.
Features
- Works on all Swift compatible platforms (Linux, Android, and Windows included)
- Easy to use
- Well documented (100% documented)
- Well tested (100% of code coverage)
- Create an operation block
- Create a single operation
- Create chained operations
- Manage a centralized queue
- Create unlimited queues
- Declare how many concurrent operations a queue can handle
- Create semaphores
- Create and handle schedules
- Automatically or manually retry an operation
- Throttling between each automatic operation retry
- Syntactic sugar to create and chain operations easier and faster
- Async/await operations with automatic retries on thrown errors
- Builds in the Swift 6 language mode with strict concurrency
Compatibility
| Swift | Queuer | iOS | macOS | macCatalyst | tvOS | watchOS | visionOS | Linux | Android | Windows |
|---|---|---|---|---|---|---|---|---|---|---|
| 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...3.0.1 | 12.0+ | 10.13+ | 13.0+ | 12.0+ | 4.0+ | 1.0+ | ✅ | ||
| 5.9...6.3 | 4.0.0 | 12.0+ | 10.13+ | 13.0+ | 12.0+ | 4.0+ | 1.0+ | ✅ | ✅ | ✅ |
[!NOTE] Some APIs require a newer OS than the minimum deployment target:
AsyncConcurrentOperation,addChainedAsyncOperations(_:completionHandler:),addAsyncCompletionHandler(_:),addBarrier(_:), andbarrier(_:)require macOS 10.15, iOS 13, tvOS 13, or watchOS 6.asyncWait(_:tolerance:clock:)requires macOS 13, iOS 16, tvOS 16, or watchOS 9.On Linux, Android, and Windows every API is always available.
Installing
See Requirements section to check Swift, Queuer, and OS versions.
In your Package.swift Swift Package Manager manifest, add the following dependency to your dependencies argument:
.package(url: "https://github.com/FabrizioBrancati/Queuer.git", from: "4.0.0"),
Add the dependency to any targets you've declared in your manifest:
.target(
name: "MyTarget",
dependencies: [
.product(name: "Queuer", package: "Queuer"),
]
),
Usage
- Using the Shared Queuer
- Create a Custom Queue
- Create an Operation Block
- Use Chained Operations
- Use Group Operations
- Available Queue States
- Control Operation States
- Use a Synchronous Queue
- Create a Custom Operation
- Automatically Retry an Operation
- Throttle Automatic Retries
- Manually Retry an Operation
- Manually Finish an Operation
- Async Task in an Operation
- Create an Async Operation
- Set Up a Scheduler
- Use a Semaphore
- Syntactic Sugar
Using the Shared Queuer
Queuer offers a shared instance that you can use to add operations to a centralized queue:
Queuer.shared.addOperation(operation)
Create a Custom Queue
You can also create a custom queue:
let queue = Queuer(name: "MyCustomQueue")
You can even create a queue by defining the maxConcurrentOperationCount and the qualityOfService properties:
let queue = Queuer(name: "MyCustomQueue", maxConcurrentOperationCount: Int.max, qualityOfService: .default)
Create an Operation Block
You have three methods to add an Operation block.
Directly on the
queue(orQueuer.shared):queue.addOperation { /// Your task here }Creating a
ConcurrentOperationwith a block:let concurrentOperation = ConcurrentOperation { _ in /// Your task here } queue.addOperation(concurrentOperation)
[!NOTE] We will see how
ConcurrentOperationworks later.
Use Chained Operations
Chained Operations are Operations that add a dependency each other.
They follow the given array order, for example: [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
}
You can also add a completionHandler after the queue creation with:
queue.addCompletionHandler {
/// Your completion task here
}
Use Group Operations
Group Operations are Operations that handles a group of Operations with a completion handler.
Allows the execution of a block of Operations with a completion handler that will be called once all the operations are finished, for example: [A -> [[B & C & D] -> completionHandler] -> E] -> completionHandler.
It should usually be used with a 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
}
In this case the output will be the following one: [[A & B -> completionHandler] -> C] -> completionHandler.
Available Queue States
There are a few method to handle the queue states.
Cancel all
Operations in a queue:queue.cancelAll()Pause a queue:
queue.pause()
[!WARNING] By calling
pause()you will not be sure that everyOperationwill be paused. If theOperationis already started it will not be on pause until it's a customOperationthat overridespause()function.
Resume a queue:
queue.resume()
[!WARNING] To h