CocoaPods trunk is moving to be read-only. Read more on the blog, there are 19 months to go.

Do 0.8.2

Do 0.8.2

TestsTested
LangLanguage SwiftSwift
License MIT
ReleasedLast Release Jun 2015
SPMSupports SPM

Maintained by Mathew Huusko V.



Do 0.8.2

Do!

A Swift-er way to do GCD-related things.

Installation

Manual

Drag Do-[Swift version].swift into your project.

Usage

Contents

  • Queues (access to global queues, and current queue checking)
  • Sync (deadlock safe dispatch_sync/dispatch_barrier_sync with return values)
  • Loop (deadlock safe dispatch_apply with range version)
  • After (cancellable dispatch_after)
  • Concurrent (simple mechanism for async operations with a limit to how many can process concurrently)
  • Once (hackery-enabled succinct dispatch_once)
  • Throttle (hackery-enabled succinct throttling)
  • Async (convenience functions related to dispatch_async)

Queues

Do! provides easy access to the main queue, global priority queues, as well as the global ‘quality of service’ queues available in OS X 10.10 and iOS 8.0 and later (with appropriate fallbacks in place).

Do.mainQueue // The "main" dispatch queue.

Do.highPriorityQueue // The global "high priority" dispatch queue.

Do.defaultQueue // The global "default" dispatch queue.

Do.lowPriorityQueue // The global "low priority" dispatch queue.

Do.backgroundQueue // The global "background" dispatch queue.

Do.userInteractiveQueue // The global "user interactive" (super high priority?) dispatch queue.

Do.userInitiatedQueue // The global "user initiated" (equivalent to "high priority") dispatch queue.

Do.utilityQueue // The global "utility" (equivalent to "low priority") dispatch queue.

Do! also provides a way to check whether you are currently dispatched on a specific queue by comparing labels (give your queues labels!).

if Do.isCurrentQueue(mainQueue) {
    print("Hello from the main queue!")
}

Sync

Do! provides a wrapper around dispatch_sync and dispatch_barrier_sync that is succinct and deadlock safe (well, more deadlock safe – it uses Do.isCurrentQueue to avoid this, but that only helps if you try to dispatch to the current queue, not one higher up in the dispatch tree).

Do.sync(someSerialQueue) {
    print("Hello world!")
}
Do.barrierSync(someConcurrentQueue) {
    print("Hello world!")
}

More importantly, Do! provides versions which returns values, which is perfect for synchronizing access to resources…

let resource: Resource = Do.sync(someSerialQueue) {
    // .. heavy work that should happen serially...

    return importantResource
}
let resource: Resource = Do.barrierSync(someConcurrentQueue) {
    // .. heavy work that should block queue...

    return importantResource
}

.. or even synchronizing properties.

class Variable {
    private var _value: Any

    var value: Any {
        get { return barrierSync(someConcurrentQueue) { self._value } }
        set { barrierSync(someConcurrentQueue) { self._value = newValue } }
    }
}

Loop

Do! provides a wrapper around dispatch_apply that is succinct and deadlock safe (again, more deadlock safe). If the targetted queue is the current dispatch queue (or nil), it reverts to a plain loop.

Do.loop(100, highPriorityQueue) { i in
    print(i)
}
Do.loop(10) { i in
    print(i)
}

Do! also provides a version which takes a range instead of an iterations count.

Do.loop(15..<55, highPriorityQueue) { i in
    print(i)
}

After

Do! provides a wrapper around dispatch_after that is succinct and defaults to the main queue…

Do.after(3.0) {
    print("Hello world!")
}
Do.after(0.5, backgroundQueue) {
    print("Hello world!")
}

.. as well as a version returning a block for cancellation of the scheduled dispatch.

let cancel = Do.afterCancel(10) {
    print("Hello world!")
}

Do.after(2) {
    cancel()
}

Concurrent

Do! provides a simple but powerful mechanism for dispatching async operations (which might have async/nested dispatches themselves) that can be limited to processing sequentially or N at a time.

static token = Do.ConcurrentToken() // store this somewhere!

// ...

for i in 0..<100 {
    Do.concurrent(token, highPriorityQueue) { done in
        // some heavy stuff...

        done()
    }
}

// the 100 operations will process one at a time...
static token = Do.ConcurrentToken(limit: 5)

for i in 0..<50 {
    Do.concurrent(token, mainQueue) { done in
        Do.after(0.5) {
            done()        
        }
    }

    Do.concurrent(token, backgroundQueue) { done in
        Do.after(1.0) {
            done()        
        }
    }
}

// the 100 operations (with different logic/queues) will process 5 at a time

Once

Do! provides an uber-succinct wrapper around dispatch_once (using hackery.. so beware, it works/is stable, but is not guaranteed to be the most performant solution).

Do.once {
    print("Hello world!")
}

Do! also provides a version which stores the result of the initial dispatch, and simply returns the value on all subsequent dispatches (again, hackery).

for i in 0..<10 {
    let message: String = Do.once {
        print("Some lazy/heavy stuff that should only happen once ;)")

        return "Hello world!"
    }

    print(message)
}

Throttle

Do! provides an uber-succinct way to dispatch a block a max of once per N seconds (again, hackery).

Do.throttle(3.4) {
    print("Hello world!")
}
Do.throttle(0.5, backgroundQueue) {
    print("Hello world!")
}

Async

Do! provides a wrapper around dispatch_async that is succinct, and convenient. That’s it really, though. For added features (e.g. chaining) I recommend Async by duemunk.

Do.async(userInitiatedQueue) { ... }
Do.barrierAsync(userInitiatedQueue) { ... }
let group = dispatch_group_create()

Do.groupAsync(group, userInitiatedQueue) { ... }

Do.barrierGroupAsync(group, userInitiatedQueue) { ... }
Do.main { ... }

Do.background { ... }

Do.userInteractive { ... }

Do.userInitiated { ... }