Delay

Delay

A Swift micro-library that enables easy and cancellable delayed execution of blocks.

5ed56f83 Update Cartfile · by Aral Balkan

Delay

Delay is an easy-to-use micro-library for delaying code execution in a cancellable manner. It uses Grand Central Dispatch and blocks.

Installation

Carthage compatible

1. Update your Cartfile

Swift 3 (latest version)

git "git@source.ind.ie:project/delay.git" ~> 3.0

For Swift 2.3, use the swift-2.3 branch:

git "git@source.ind.ie:project/delay.git" "swift-2.3"

To stay on Swift 2.2, use the 2.0.3 tag:

git "git@source.ind.ie:project/handle.git" ~> 2.0.3

2. Add the framework to your Xcode project

Follow the instructions on Carthage’s readme.

Demos

  1. Run the ./install script to install the dependencies for the demo apps.
  2. Run the ./dev script and play with the iOS and macOS demo apps.

Usage

Delay has three main use cases:

  • Delay execution of a block to the next stack frame (next frame of the runloop)
  • Delay execution by N seconds
  • Delay execution in a cancellable manner

Execute on next stack frame

_ = delay(0.0)
{
  // Do something.
}

Execute after an arbitrary number of seconds

_ = delay(42.0)
{
  // Do something.
}

Cancel before execution

let cancellableBlock = delay(42.0)
{
  // Do something.
}
cancellableBlock.cancel()

Idiom: throttle user input

var cancellableCommand:CancellableDelayedCommand?

// …

// Throttle expensive operation so it is performed at
// most every second, no matter how often a signal is received.
cancellableCommand = cancellableCommand?.reset() ?? delay(1.0)
{
  // Perform expensive operation:
  // …
}

For example, you can use this to implement auto-complete without flooding the lookup method on every keystroke.

var textDidChangeHandler:NotificationHandler?
var cancellableAutoCompleteCommand:CancellableDelayedCommand?

// …

override func viewWillAppear()
{
  textDidChangeHandler = handle(NSControlTextDidChangeNotification, from: myTextInput)
  {
    /* with */ notification in

    let text = self.myTextInput.stringValue

    // Throttle auto-complete lookups to every 1/3rd of a second.
    cancellableAutoCompleteCommand = cancellableAutoCompleteCommand?.reset() ?? delay(0.3)
    {
      // Perform expensive operation: look-up text for auto-complete
      // …
    }
  }
}

override func viewWillDisappear()
{
  cancellableAutoCompleteCommand.cancel()
  textDidChangeHandler.remove()
}

Read more about the library in this blog post on Ind.ie Labs.

On performance

Note that Delay is optimised for ease of authoring, beauty of interface, and clarity of intent. I haven’t run into performance issues and hence haven’t felt the need to run any benchmarks at the moment but Evgenii Rtishchev’s purely-block-based CancelBlocks, on which my solution is based, is a lighter alternative should you need it.

Credits

Delay based on the work of Evgenii Rtishchev and Chris Brind (with thanks to Cezary Wojcik.)

Copyright © Aral Balkan. Released with ♥ by Ind.ie under the MIT License.