readme.md 4.98 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

Aral Balkan's avatar
Aral Balkan committed
5 6
**This is the master branch (Swift 2.2.1).** Also available: [Swift 2.3](https://source.ind.ie/project/delay/tree/swift-2.3) and [Swift 3](https://source.ind.ie/project/delay/tree/swift-3) branch

7 8 9 10
## Installation

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

11
Run the `./install` script to install the dependencies for the demo apps.
12

13
See the [detailed installation instructions](#detailed-installation-instructions), below, for instructions on how to add Delay to your own apps.
14

15
## Getting started
16

17
Run the `./dev` script and play with the iOS and OS X demo apps.
Aral Balkan's avatar
Aral Balkan committed
18

19
## Usage
Aral Balkan's avatar
Aral Balkan committed
20 21 22 23 24 25 26 27 28

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

29 30 31 32 33 34
```swift
delay(0.0)
{
  // Do something.
}
```
Aral Balkan's avatar
Aral Balkan committed
35 36 37

### Execute after an arbitrary number of seconds

38 39 40 41 42 43
```swift
delay(42.0)
{
  // Do something.
}
```
Aral Balkan's avatar
Aral Balkan committed
44 45
### Cancel before execution

46 47 48 49 50 51 52
```swift
let cancellableBlock = delay(42.0)
{
  // Do something.
}
cancellableBlock.cancel()
```
Aral Balkan's avatar
Aral Balkan committed
53 54 55

### Idiom: throttle user input

56 57
```swift
var cancellableCommand:CancellableDelayedCommand?
Aral Balkan's avatar
Aral Balkan committed
58

59
// …
Aral Balkan's avatar
Aral Balkan committed
60

61 62 63 64 65 66 67 68
// 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
69 70 71

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

72 73 74
```swift
var textDidChangeHandler:NotificationHandler?
var cancellableAutoCompleteCommand:CancellableDelayedCommand?
Aral Balkan's avatar
Aral Balkan committed
75

76
// …
Aral Balkan's avatar
Aral Balkan committed
77

78 79 80 81 82
override func viewWillAppear()
{
	textDidChangeHandler = handle(NSControlTextDidChangeNotification, from: myTextInput)
  {
    /* with */ notification in
83

84
    let text = self.myTextInput.stringValue
85

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

95 96 97 98 99 100
override func viewWillDisappear()
{
  cancellableAutoCompleteCommand.cancel()
  textDidChangeHandler.remove()
}
```
Aral Balkan's avatar
Aral Balkan committed
101 102 103 104 105 106 107

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.

108 109
## Detailed installation instructions

110
### Carthage
111

112
1. Add the framework to your `Cartfile`. e.g.,
113 114 115 116 117 118 119 120 121 122 123 124

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

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

### Manual

#### iOS

This requires hacking the Xcode project file but it’s still the most elegant way of doing things. If you want a better way, [dupe this radar for seamless support of fat frameworks in Xcode](http://openradar.appspot.com/radar?id=4951631992979456).

1. Build the framework target.
Aral Balkan's avatar
Aral Balkan committed
125
2. In Xcode, add the framework to the Embedded Binaries section.
126 127 128 129 130 131 132 133
3. Edit the `project.pbxproj` (in the <your-project>.xcodeproj folder) file and replace the line that reads something like:

	```A7E653511C2496F700988537 /* Delay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Delay.framework; path = "../../path/in/DerivedData/to/Delay.framework"; sourceTree = "<group>"; };```

	With:

	```A7E653511C2496F700988537 /* Delay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Delay.framework; path = "$(CONFIGURATION_BUILD_DIR)/Delay.framework"; sourceTree = "<group>"; };```

Aral Balkan's avatar
Aral Balkan committed
134
(In other words, you’re replacing the hardcoded path to the framework within your particular Derived Data folder with a generic one. This means that anyone else who checks out your project will get the correct framework.)
135 136 137 138 139 140 141

#### OS X

1. Just drag the framework into the Linked Frameworks and Binaries section of your project (under General).

(For an example of manually adding the framework, see the iOS and OS X demo apps that ship with this framework.)

Aral Balkan's avatar
Aral Balkan committed
142 143 144 145
## 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).)

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