readme.md 3.38 KB
Newer Older
Aral Balkan's avatar
Aral Balkan committed
1 2
# Delay

3
Delay is an easy-to-use micro-library for delaying code execution in a cancellable manner. It uses Grand Central Dispatch and blocks.
Aral Balkan's avatar
Aral Balkan committed
4

5 6 7 8
## Installation

[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)

Aral Balkan's avatar
Aral Balkan committed
9
### 1. Update your Cartfile
Aral Balkan's avatar
Aral Balkan committed
10

11
**Swift 3 (latest version) – master**
Aral Balkan's avatar
Aral Balkan committed
12 13

```
14
git "git@source.ind.ie:project/delay.git"
Aral Balkan's avatar
Aral Balkan committed
15 16
```

Aral Balkan's avatar
Aral Balkan committed
17
For Swift 2.3, use the swift-2.3 branch:
18

Aral Balkan's avatar
Aral Balkan committed
19 20 21
```
git "git@source.ind.ie:project/delay.git" "swift-2.3"
```
22

Aral Balkan's avatar
Aral Balkan committed
23
### 2. Add the framework to your Xcode project
Aral Balkan's avatar
Aral Balkan committed
24 25 26 27

[Follow the instructions on Carthage’s readme](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application).

## Demos
28

Aral Balkan's avatar
Aral Balkan committed
29 30
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.
Aral Balkan's avatar
Aral Balkan committed
31

32
## Usage
Aral Balkan's avatar
Aral Balkan committed
33 34 35 36 37 38 39 40 41

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

42
```swift
Aral Balkan's avatar
Aral Balkan committed
43
_ = delay(0.0)
44 45 46 47
{
  // Do something.
}
```
Aral Balkan's avatar
Aral Balkan committed
48 49 50

### Execute after an arbitrary number of seconds

51
```swift
Aral Balkan's avatar
Aral Balkan committed
52
_ = delay(42.0)
53 54 55 56
{
  // Do something.
}
```
Aral Balkan's avatar
Aral Balkan committed
57 58
### Cancel before execution

59 60 61 62 63 64 65
```swift
let cancellableBlock = delay(42.0)
{
  // Do something.
}
cancellableBlock.cancel()
```
Aral Balkan's avatar
Aral Balkan committed
66 67 68

### Idiom: throttle user input

69 70
```swift
var cancellableCommand:CancellableDelayedCommand?
Aral Balkan's avatar
Aral Balkan committed
71

72
// …
Aral Balkan's avatar
Aral Balkan committed
73

74 75 76 77 78 79 80 81
// 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:
  // …
}
```
Aral Balkan's avatar
Aral Balkan committed
82 83 84

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

85 86 87
```swift
var textDidChangeHandler:NotificationHandler?
var cancellableAutoCompleteCommand:CancellableDelayedCommand?
Aral Balkan's avatar
Aral Balkan committed
88

89
// …
Aral Balkan's avatar
Aral Balkan committed
90

91 92
override func viewWillAppear()
{
Aral Balkan's avatar
Aral Balkan committed
93
  textDidChangeHandler = handle(NSControlTextDidChangeNotification, from: myTextInput)
94 95
  {
    /* with */ notification in
96

97
    let text = self.myTextInput.stringValue
98

99 100 101 102 103 104 105 106
    // 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
      // …
    }
  }
}
Aral Balkan's avatar
Aral Balkan committed
107

108 109 110 111 112 113
override func viewWillDisappear()
{
  cancellableAutoCompleteCommand.cancel()
  textDidChangeHandler.remove()
}
```
Aral Balkan's avatar
Aral Balkan committed
114 115 116 117 118

Read more about the library [in this blog post](https://ind.ie/labs/blog/delay) on [Ind.ie Labs](https://ind.ie/labs).

## On performance

Aral Balkan's avatar
Aral Balkan committed
119
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](https://github.com/katleta3000/CancelBlocks/blob/master/CancelBlocks.swift), on which my solution is based, is a lighter alternative should you need it.
Aral Balkan's avatar
Aral Balkan committed
120 121 122 123 124

## Credits

Delay based on the work of [Evgenii Rtishchev](https://github.com/katleta3000/CancelBlocks) and [Chris Brind](http://stackoverflow.com/questions/24034544/dispatch-after-gcd-in-swift/24318861#24318861) (with thanks to [Cezary Wojcik](http://stackoverflow.com/a/24034838/253485).)

125
Copyright © Aral Balkan.
126
Released with ♥ by [Ind.ie](https://ind.ie) under the MIT License.