Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
Swift Shell Ruby Objective-C
Switch branches/tags
Nothing to show
Latest commit eab3ab3 Aug 17, 2017 @FabrizioBrancati Improving tests

README.md

Queuer Banner

Build Status Codecov Documentation codebeat Swift Package Manager Compatible Carthage Compatible Version License
Language Platforms


Swift 4FeaturesRequirementsInstallingUsageDocumentationChangelogCommunicationContributingAuthorLicense


Swift 4

If you need Swift 4 support, please switch to swift-4 branch.

Features

Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
It allows you to create any synchronous and asynchronous task easily, 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 (currently 99% 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 a network request operation *
  • Create a network download operation *
  • Create a network upload operation *
  • Ability to restore uncompleted network operations *

* Currently, URLSession.shared property is not yet implemented on Linux.

Requirements

Swift Xcode Queuer iOS macOS tvOS watchOS Linux
3.1....3.2 8.3...9.0 1.0.0 8.0+ 10.10 9.0 2.0+ ✓ *
4.0 9.0 ?.?.0 8.0+ 10.10 9.0 2.0+ ✓ *

* Currently, URLSession.shared property is not yet implemented on Linux.

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

    and add the paths to the Queuer framework under Input Files

    $(SRCROOT)/Carthage/Build/iOS/Queuer.framework

    This script works around an App Store submission bug triggered by universal binaries and ensures that necessary bitcode-related files are copied when archiving

  • Import the framework with import Queuer

  • Enjoy!

Swift Package Manager

  • Create a Package.swift file in your project directory and write into:

    import PackageDescription
    
    let package = Package(
        name: "Project",
        dependencies: [
            .Package(url: "https://github.com/FabrizioBrancati/Queuer.git", majorVersion: 1)
        ]
    )
  • 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

Queuer.shared.addOperation(operation)

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)

* Currently, QualityOfService property is not directly supported on Linux, since there are not qos class promotions available outside of darwin targets.

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 {
        /// Your task here
    }
    queue.addOperation(concurrentOperation)
  • Creating a SynchronousOperation with a block:

    let synchronousOperation = SynchronousOperation {
        /// Your task here
    }
    queue.addOperation(concurrentOperation)

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 concurrentOperation1 = ConcurrentOperation {
    /// Your task 1 here
}
let concurrentOperation2 = ConcurrentOperation {
    /// Your task 2 here
}
queue.addChainedOperations([concurrentOperation1, concurrentOperation2]) {
    /// 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 or is a RequestOperation.

  • Resume queue:

    queue.resume()

    To have a complete pause and resume states you must create a custom Operation that overrides pause() and resume() function or use a RequestOperation.

  • 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.
Look at RequestOperation.swift if you are looking for an example.

For convenience it has an init function with a completion block:

let concurrentOperation = ConcurrentOperation {
    /// 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 {
  /// Your task here
}
synchronousOperation.addToQueue(queue)

Semaphore

A Semaphore is a struct that uses the GDC'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

It's more useful if used inside an asynchronous task:

let concurrentOperation = ConcurrentOperation {
    /// Your task here
    semaphore.continue()
}
concurrentOperation.addToQueue(queue)
semaphore.wait()

Request Operation *

RequestOperation allows you to easily create a network request and add it to a queue:

let requestOperation: RequestOperation = RequestOperation(url: self.testAddress) { success, response, data, error in

}
requestOperation.addToQueue(queue)

Allowed parameters in RequestOperation init function:

  • url is a String representing the request URL
  • query is Dictionary representing the request query parameters to be added to the url with ? and & characters
  • timeout is the request timeout
  • method is the request method, you can choose to one of: connect, delete, get, head, options, patch, post and put
  • cachePolicy is the request cache policy, referrer to CachePolicy documentation
  • headers is a Dictionary representing the request headers
  • body is a Data representing the request body
  • completionHandler is the request response handler

Response handler variables:

  • success is a Bool indicating if the request was successful. It's successful if its status is between 200 and 399, it wasn't cancelled and did't get any other network error.
  • respose is an HTTPURLResponse instance. It contains all the response headers and the status code. May be nil.
  • data is a Data instance with the request body. You must convert, to a JSON or String in example, it in order to use. May be nil.
  • error is an Error instance with the request error. May be nil.

It can be paused, resumed, cancelled and chained with other Operations.

* Currently, URLSession.shared property is not yet implemented on Linux.

Documentation

Documentation

100% Documented

Changelog

To see what has changed in recent versions of Queuer, see the CHANGELOG.md file.

Communication

  • If you need help, open an issue.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, see Contributing section.

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.