Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
It allows you to create any asynchronous and synchronous task easily, all managed by a queue, with just a few lines.
Here is the list of all the features:
Works on all Swift compatible platforms (even Linux)
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 queue
Declare how many concurrent operation a queue can handle
Create semaphores
Create and handle schedules
Automatically or manually retry an operation
Ability to restore uncompleted operations
Improve the state restoration feature
Throttling between each automatic operation retry
Data layer that every operation inside an OperationQueue can access
Requirements
Swift
Xcode
Queuer
iOS
macOS
tvOS
watchOS
Linux
3.1…3.2
8.3…9.0
1.0.0…1.1.0
8.0+
10.10+
9.0+
2.0+
4.0
9.0…9.2
1.3.0
8.0+
10.10+
9.0+
2.0+
4.1
9.3…9.4
1.3.1…1.3.2
8.0+
10.10+
9.0+
2.0+
4.2
10.0…10.1
2.0.0…2.0.1
8.0+
10.10+
9.0+
3.0+
5.0…5.1
10.2…11.2
2.1.0…2.1.1
8.0+
10.10+
9.0+
3.0+
Installing
See Requirements section to check Swift, Xcode, Queuer and OS versions.
Manual
Open and build the framework from the project (Queuer.xcodeproj)
Import Queuer.framework into your project
Import the framework with import Queuer
Enjoy!
CocoaPods
Create a Podfile in your project directory and write into:
platform :ios, '8.0'
xcodeproj 'Project.xcodeproj'
use_frameworks!
pod 'Queuer'
Change “Project” with your real project name
Open Terminal, go to your project directory and type: pod install
Import the framework with import Queuer
Enjoy!
Carthage
Create a Cartfile in your project directory and write into:
github "FabrizioBrancati/Queuer"
Open Terminal, go to project directory and type: carthage update
Include the created Framework in your project
Add Build Phase with the following contents:
/usr/local/bin/carthage copy-frameworks
Add the paths to the Queuer framework under Input Files
$(SRCROOT)/Carthage/Build/iOS/Queuer.framework
Add the paths to the copied frameworks to the Output Files
This script works around an App Store submission bug triggered by universal binaries and ensures that necessary bitcode-related files are copied when archiving
(Optional) Add Build Phase with the following contents
/usr/local/bin/carthage outdated --xcode-warnings
To automatically warn you when one of your dependencies is out of date
Import the framework with import Queuer
Enjoy!
Swift Package Manager
Create a Package.swift file in your project directory and write into:
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(or Queuer.shared):
queue.addOperation {
/// Your task here
}
Creating a ConcurrentOperation with a block:
let concurrentOperation = ConcurrentOperation { _ in
/// Your task here
}
queue.addOperation(concurrentOperation)
Creating a SynchronousOperation with a block:
let synchronousOperation = SynchronousOperation { _ in
/// Your task here
}
queue.addOperation(synchronousOperation)
We will see how ConcurrentOperation and SynchronousOperation works later.
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
}
Queue States
Cancel all Operations in queue:
queue.cancelAll()
Pause queue:
queue.pause()
By calling pause() you will not be sure that every Operation will be paused.
If the Operation is already started it will not be on pause until it’s a custom Operation that overrides pause() function.
Resume queue:
queue.resume()
To have a complete pause and resume states you must create a custom Operation that overrides pause() and resume() function.
Wait until all Operations are finished:
queue.waitUntilAllOperationsAreFinished()
This function means that the queue will blocks the current thread until all Operations are finished.
Asynchronous Operation
ConcurrentOperation is a class created to be subclassed.
It allows synchronous and asynchronous tasks, has a pause and resume states, can be easily added to a queue and can be created with a block.
You can create your custom ConcurrentOperation by subclassing it.
You must override execute() function and call the finish() function inside it, when the task has finished its job to notify the queue.
For convenience it has an init function with a completion block:
let concurrentOperation = ConcurrentOperation { _ in
/// Your task here
}
concurrentOperation.addToQueue(queue)
Synchronous Operation
There are three methods to create synchronous tasks or even queue:
Setting maxConcurrentOperationCount of the queue to 1.
By setting that property to 1 you will be sure that only one task at time will be executed.
Using a Semaphore and waiting until a task has finished its job.
Using a SynchronousOperation.
It’s a subclass of ConcurrentOperation that handles synchronous tasks.
It’s not awesome as it seems to be and is always better to create an asynchronous task, but some times it may be useful.
For convenience it has an init function with a completion block:
let synchronousOperation = SynchronousOperation { _ in
/// Your task here
}
synchronousOperation.addToQueue(queue)
Automatically Retry an Operation
An Operation is passed to every closure, with it you can set and handle the retry feature.
By default the retry feature is disabled, to enable it simply set the success property to false. With success to false the Operation will retry until reaches maximumRetries property value. To let the Operation know when everything is ok, you must set success to true.
With currentAttempt you can know at which attempt the Operation is.
let concurrentOperation = ConcurrentOperation { operation in
/// Your task here
if /* Successful */ {
operation.success = true
} else {
operation.success = false
}
}
Manually Retry an Operation
You can manually retry an Operation when you think that the execution will be successful.
An Operation is passed to every closure, with it you can set and handle the retry feature.
By default the manual retry feature is disabled, to enable it simply set the manualRetry property to true, you must do this outside of the execution closure. You must also set success to true or false to let the Operation know when is everything ok, like the automatic retry feature.
To let the Operation retry your execution closure, you have to call the retry() function. If the retry() is not called, you may block the entire queue. Be sure to call it at least maximumRetries times, it is not a problem if you call retry() more times than is needed, your execution closure will not be executed more times than the maximumRetries value.
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()
Scheduler
A Scheduler is a struct that uses the GDC’s DispatchSourceTimer to create a timer that can execute functions with a specified interval and quality of service.
let schedule = Scheduler(deadline: .now(), repeating: .seconds(1)) {
/// Your task here
}
You can even create a Scheduler without the handler and set it later:
var schedule = Scheduler(deadline: .now(), repeating: .seconds(1))
schedule.setHandler {
/// Your task here.
}
With timer property you can access to all DispatchSourceTimer properties and functions, like cancel():
schedule.timer.cancel()
Semaphore
A Semaphore is a struct that uses the GCD’s DispatchSemaphore to create a semaphore on the function and wait until it finish its job.
I recommend you to use a defer { semaphore.continue() } right after the Semaphore creation and wait() call.
let semaphore = Semaphore()
semaphore.wait()
defer { semaphore.continue() }
/// Your task here
You can even set a custom timeout, default is .distantFuture:
It’s more useful if used inside an asynchronous task:
let concurrentOperation = ConcurrentOperation {
/// Your task here
semaphore.continue()
}
concurrentOperation.addToQueue(queue)
semaphore.wait()
Queue State Restoration (Beta)
To enable the Queue Restoration feature you must use ConcurrentOperation with a unique (non-nil) name property.
Currently this feature allows you to save the current state (OperationStates) of your queue, like: name, progress and dependencies.
The progress property allows to save the current state of the Operation progress. Update it constantly during the Operation execution.
Call Queuer.state(of: OperationQueue) or operationQueue.state() to get the QueueStateList aka: Array of OperationStates.
It’s up to you save and retrieve this list, and create the queue correctly.
Features • Requirements • Installing • Usage • Documentation • Changelog • Communication • Contributing • Author • License
Features
Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
It allows you to create any asynchronous and synchronous task easily, all managed by a queue, with just a few lines.
Here is the list of all the features:
OperationQueue
can accessRequirements
Installing
See Requirements section to check Swift, Xcode, Queuer and OS versions.
Manual
import Queuer
CocoaPods
Create a Podfile in your project directory and write into:
Change “Project” with your real project name
Open Terminal, go to your project directory and type:
pod install
Import the framework with
import Queuer
Enjoy!
Carthage
Create a Cartfile in your project directory and write into:
Open Terminal, go to project directory and type:
carthage update
Include the created Framework in your project
Add Build Phase with the following contents:
Add the paths to the Queuer framework under Input Files
Add the paths to the copied frameworks to the Output Files
This script works around an App Store submission bug triggered by universal binaries and ensures that necessary bitcode-related files are copied when archiving
(Optional) Add Build Phase with the following contents
To automatically warn you when one of your dependencies is out of date
Import the framework with
import Queuer
Enjoy!
Swift Package Manager
Create a Package.swift file in your project directory and write into:
Change “Project” with your real project name
Open Terminal, go to project directory and type:
swift build
Import the framework with
import Queuer
Enjoy!
Usage
Shared Queuer
Custom Queue
You can even create a queue by defining the
maxConcurrentOperationCount
and thequalityOfService
properties:Create an Operation Block
You have three methods to add an
Operation
block:Directly on the
queue
(orQueuer.shared
):Creating a
ConcurrentOperation
with a block:Creating a
SynchronousOperation
with a block:Chained Operations
Chained Operations are
Operation
s that add a dependency each other.They follow the given array order, for example:
[A, B, C] = A -> B -> C -> completionBlock
.You can also add a
completionHandler
after the queue creation with:Queue States
Cancel all
Operation
s in queue:Pause queue:
Resume queue:
Wait until all
Operation
s are finished:Asynchronous Operation
ConcurrentOperation
is a class created to be subclassed. It allows synchronous and asynchronous tasks, has a pause and resume states, can be easily added to a queue and can be created with a block.You can create your custom
ConcurrentOperation
by subclassing it.You must override
execute()
function and call thefinish()
function inside it, when the task has finished its job to notify the queue.For convenience it has an
init
function with a completion block:Synchronous Operation
There are three methods to create synchronous tasks or even queue:
maxConcurrentOperationCount
of the queue to1
.By setting that property to
1
you will be sure that only one task at time will be executed.Semaphore
and waiting until a task has finished its job.SynchronousOperation
.It’s a subclass of
ConcurrentOperation
that handles synchronous tasks.It’s not awesome as it seems to be and is always better to create an asynchronous task, but some times it may be useful.
For convenience it has an
init
function with a completion block:Automatically Retry an Operation
An
Operation
is passed to every closure, with it you can set and handle the retry feature.By default the retry feature is disabled, to enable it simply set the
success
property tofalse
. Withsuccess
tofalse
theOperation
will retry until reachesmaximumRetries
property value. To let theOperation
know when everything is ok, you must setsuccess
totrue
.With
currentAttempt
you can know at which attempt theOperation
is.Manually Retry an Operation
You can manually retry an
Operation
when you think that the execution will be successful.An
Operation
is passed to every closure, with it you can set and handle the retry feature.By default the manual retry feature is disabled, to enable it simply set the
manualRetry
property totrue
, you must do this outside of the execution closure. You must also setsuccess
totrue
orfalse
to let theOperation
know when is everything ok, like the automatic retry feature.To let the
Operation
retry your execution closure, you have to call theretry()
function. If theretry()
is not called, you may block the entire queue. Be sure to call it at leastmaximumRetries
times, it is not a problem if you callretry()
more times than is needed, your execution closure will not be executed more times than themaximumRetries
value.Scheduler
A
Scheduler
is a struct that uses the GDC’sDispatchSourceTimer
to create a timer that can execute functions with a specified interval and quality of service.You can even create a
Scheduler
without the handler and set it later:With
timer
property you can access to allDispatchSourceTimer
properties and functions, likecancel()
:Semaphore
A
Semaphore
is a struct that uses the GCD’sDispatchSemaphore
to create a semaphore on the function and wait until it finish its job.I recommend you to use a
defer { semaphore.continue() }
right after theSemaphore
creation andwait()
call.You can even set a custom timeout, default is
.distantFuture
:It’s more useful if used inside an asynchronous task:
Queue State Restoration (Beta)
To enable the Queue Restoration feature you must use
ConcurrentOperation
with a unique (non-nil)name
property. Currently this feature allows you to save the current state (OperationState
s) of your queue, like:name
,progress
anddependencies
.The
progress
property allows to save the current state of theOperation
progress. Update it constantly during theOperation
execution.Call
Queuer.state(of: OperationQueue)
oroperationQueue.state()
to get theQueueStateList
aka: Array ofOperationState
s.It’s up to you save and retrieve this list, and create the queue correctly.
Documentation
Jazzy Generated Documentation - 100% Documented
Changelog
To see what has changed in recent versions of Queuer, see the CHANGELOG.md file.
Communication
Contributing
See CONTRIBUTING.md file.
Author
Fabrizio Brancati
Website: https://www.fabriziobrancati.com
Email: fabrizio.brancati@gmail.com
License
Queuer is available under the MIT license. See the LICENSE file for more info.