readme.md 3.47 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)**
Aral Balkan's avatar
Aral Balkan committed
12 13

```
Aral Balkan's avatar
Aral Balkan committed
14
git "git@source.ind.ie:project/delay.git" ~> 3.0
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
To stay on Swift 2.2, use the 2.0.3 tag:
24 25

```
Aral Balkan's avatar
Aral Balkan committed
26
git "git@source.ind.ie:project/handle.git" ~> 2.0.3
27 28
```

Aral Balkan's avatar
Aral Balkan committed
29 30 31 32 33
### 2. Add to your project

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

### 3. Run the `./install` script
34

Aral Balkan's avatar
Aral Balkan committed
35
This will install the dependencies for the demo apps.
36

Aral Balkan's avatar
Aral Balkan committed
37
## Demos
38

Aral Balkan's avatar
Aral Balkan committed
39
Run the `./dev` script and play with the iOS and macOS demo apps.
Aral Balkan's avatar
Aral Balkan committed
40

41
## Usage
Aral Balkan's avatar
Aral Balkan committed
42 43 44 45 46 47 48 49 50

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

51
```swift
Aral Balkan's avatar
Aral Balkan committed
52
_ = delay(0.0)
53 54 55 56
{
  // Do something.
}
```
Aral Balkan's avatar
Aral Balkan committed
57 58 59

### Execute after an arbitrary number of seconds

60
```swift
Aral Balkan's avatar
Aral Balkan committed
61
_ = delay(42.0)
62 63 64 65
{
  // Do something.
}
```
Aral Balkan's avatar
Aral Balkan committed
66 67
### Cancel before execution

68 69 70 71 72 73 74
```swift
let cancellableBlock = delay(42.0)
{
  // Do something.
}
cancellableBlock.cancel()
```
Aral Balkan's avatar
Aral Balkan committed
75 76 77

### Idiom: throttle user input

78 79
```swift
var cancellableCommand:CancellableDelayedCommand?
Aral Balkan's avatar
Aral Balkan committed
80

81
// …
Aral Balkan's avatar
Aral Balkan committed
82

83 84 85 86 87 88 89 90
// 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
91 92 93

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

94 95 96
```swift
var textDidChangeHandler:NotificationHandler?
var cancellableAutoCompleteCommand:CancellableDelayedCommand?
Aral Balkan's avatar
Aral Balkan committed
97

98
// …
Aral Balkan's avatar
Aral Balkan committed
99

100 101
override func viewWillAppear()
{
Aral Balkan's avatar
Aral Balkan committed
102
  textDidChangeHandler = handle(NSControlTextDidChangeNotification, from: myTextInput)
103 104
  {
    /* with */ notification in
105

106
    let text = self.myTextInput.stringValue
107

108 109 110 111 112 113 114 115
    // 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
116

117 118 119 120 121 122
override func viewWillDisappear()
{
  cancellableAutoCompleteCommand.cancel()
  textDidChangeHandler.remove()
}
```
Aral Balkan's avatar
Aral Balkan committed
123 124 125 126 127 128 129 130 131 132 133

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

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.

## 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).)

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