├── .gitignore ├── LICENSE-THREADLY.txt ├── LICENSE.txt ├── README.md ├── docs ├── Classes.html ├── Classes │ ├── Collector.html │ ├── Imitator.html │ ├── Sink.html │ ├── Stream.html │ └── Subscription.html ├── Functions.html ├── badge.svg ├── css │ ├── highlight.css │ └── jazzy.css ├── docsets │ ├── froop.docset │ │ └── Contents │ │ │ ├── Info.plist │ │ │ └── Resources │ │ │ ├── Documents │ │ │ ├── Classes.html │ │ │ ├── Classes │ │ │ │ ├── Collector.html │ │ │ │ ├── Imitator.html │ │ │ │ ├── Sink.html │ │ │ │ ├── Stream.html │ │ │ │ └── Subscription.html │ │ │ ├── Functions.html │ │ │ ├── css │ │ │ │ ├── highlight.css │ │ │ │ └── jazzy.css │ │ │ ├── img │ │ │ │ ├── carat.png │ │ │ │ ├── dash.png │ │ │ │ └── gh.png │ │ │ ├── index.html │ │ │ ├── js │ │ │ │ ├── jazzy.js │ │ │ │ └── jquery.min.js │ │ │ └── search.json │ │ │ └── docSet.dsidx │ └── froop.tgz ├── img │ ├── carat.png │ ├── dash.png │ └── gh.png ├── index.html ├── js │ ├── jazzy.js │ └── jquery.min.js ├── search.json └── undocumented.json ├── froop.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ ├── xcbaselines │ └── 5B891BFD2222EC47002F31C6.xcbaseline │ │ ├── C6951AF0-5BDC-4962-A4A0-BEC937992614.plist │ │ └── Info.plist │ └── xcschemes │ └── froop.xcscheme ├── froop ├── Info.plist ├── Threadly.swift ├── froop.h └── froop.swift ├── froopTests ├── Info.plist └── froopTests.swift └── gen-docs.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | # 51 | # Add this line if you want to avoid checking in source code from the Xcode workspace 52 | # *.xcworkspace 53 | 54 | # Carthage 55 | # 56 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 57 | # Carthage/Checkouts 58 | 59 | Carthage/Build 60 | 61 | # fastlane 62 | # 63 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 64 | # screenshots whenever they are needed. 65 | # For more information about the recommended setup visit: 66 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 67 | 68 | fastlane/report.xml 69 | fastlane/Preview.html 70 | fastlane/screenshots/**/*.png 71 | fastlane/test_output 72 | 73 | # Code Injection 74 | # 75 | # After new code Injection tools there's a generated folder /iOSInjectionProject 76 | # https://github.com/johnno1962/injectionforxcode 77 | 78 | iOSInjectionProject/ 79 | # Xcode 80 | # 81 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 82 | 83 | ## User settings 84 | xcuserdata/ 85 | 86 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 87 | *.xcscmblueprint 88 | *.xccheckout 89 | 90 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 91 | build/ 92 | DerivedData/ 93 | *.moved-aside 94 | *.pbxuser 95 | !default.pbxuser 96 | *.mode1v3 97 | !default.mode1v3 98 | *.mode2v3 99 | !default.mode2v3 100 | *.perspectivev3 101 | !default.perspectivev3 102 | -------------------------------------------------------------------------------- /LICENSE-THREADLY.txt: -------------------------------------------------------------------------------- 1 | // Threadly.swift 2 | // Threadly 3 | // 4 | // The MIT License (MIT) 5 | // 6 | // Copyright (c) 2017 Nikolai Vazquez 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Lookback Inc 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | froop for swift 2 | =============== 3 | 4 | Functional reactive stream library for swift 5 | 6 | * Small (~20 operations) 7 | * Synchronous 8 | * No dependencies 9 | * Is FRP (ha!) 10 | 11 | ## Generate docs 12 | 13 | ```bash 14 | $ sudo gem install jazzy 15 | $ ./gen-docs.sh 16 | ``` 17 | 18 | ## License 19 | 20 | See `LICENSE.txt` and for threadly see `LICENSE-THREADLY.txt`. 21 | -------------------------------------------------------------------------------- /docs/Classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Classes Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Classes

86 |

The following classes are available globally.

87 | 88 |
89 |
90 |
91 |
    92 |
  • 93 |
    94 | 95 | 96 | 97 | Stream 98 | 99 |
    100 |
    101 |
    102 |
    103 |
    104 |
    105 |

    Stream of vaules over time. Typically created by a Sink.

    106 |
    let sink = Sink<Int>()
    107 | 
    108 | let stream = sink.stream()
    109 | let double = stream.map() { $0 * 2 }
    110 | 
    111 | sink.update(0)
    112 | sink.update(1)
    113 | ...
    114 | 
    115 | 116 |

    For some detailed notes on how a combinator is structured for ARC and thread 117 | safety, see the source code for the .map() function. All operations follow 118 | a similar pattern.

    119 | 120 | See more 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public class Stream<T>
    127 | 128 |
    129 |
    130 |
    131 |
    132 |
  • 133 |
  • 134 |
    135 | 136 | 137 | 138 | MemoryStream 139 | 140 |
    141 |
    142 |
    143 |
    144 |
    145 |
    146 |

    Specialization of Stream that has memory. Memory means that any 147 | new listener added will straight away get the last value that went through the stream.

    148 | 149 |
    150 |
    151 |

    Declaration

    152 |
    153 |

    Swift

    154 |
    public class MemoryStream<T> : Stream<T>
    155 | 156 |
    157 |
    158 |
    159 |
    160 |
  • 161 |
  • 162 |
    163 | 164 | 165 | 166 | Sink 167 | 168 |
    169 |
    170 |
    171 |
    172 |
    173 |
    174 |

    The originator of a stream of values.

    175 |
    let sink = Sink<Int>()
    176 | 
    177 | let stream = sink.stream()
    178 | 
    179 | ...
    180 | sink.update(0)
    181 | sink.update(1)
    182 | sink.end()
    183 | 
    184 | 185 | See more 186 |
    187 |
    188 |

    Declaration

    189 |
    190 |

    Swift

    191 |
    public class Sink<T>
    192 | 193 |
    194 |
    195 |
    196 |
    197 |
  • 198 |
  • 199 |
    200 | 201 | 202 | 203 | Collector 204 | 205 |
    206 |
    207 |
    208 |
    209 |
    210 |
    211 |

    Helper to collect values from a stream. Mainly useful for tests.

    212 | 213 | See more 214 |
    215 |
    216 |

    Declaration

    217 |
    218 |

    Swift

    219 |
    public class Collector<T>
    220 | 221 |
    222 |
    223 |
    224 |
    225 |
  • 226 |
  • 227 |
    228 | 229 | 230 | 231 | Subscription 232 | 233 |
    234 |
    235 |
    236 |
    237 |
    238 |
    239 |

    Subscriptions are receipts to the Stream.subscribe() operation. They 240 | can be used to unsubscribe.

    241 |
    let sink = Sink<Int>()
    242 | 
    243 | let sub = sink.stream().subscribe() { print("\($0)") }
    244 | 
    245 | sink.update(0)
    246 | sub.unsubscribe()
    247 | sink.update(1) // not received
    248 | 
    249 | 250 | See more 251 |
    252 |
    253 |

    Declaration

    254 |
    255 |

    Swift

    256 |
    public class Subscription<T>
    257 | 258 |
    259 |
    260 |
    261 |
    262 |
  • 263 |
  • 264 |
    265 | 266 | 267 | 268 | Imitator 269 | 270 |
    271 |
    272 |
    273 |
    274 |
    275 |
    276 |

    Imitators are used to create cyclic streams. The imitator is an originator 277 | of a stream at the same time as it imitates some other stream further down 278 | the code.

    279 | 280 |

    Here’s a bad idea illustrating the usage:

    281 |
    let imitator = Imitator<Int>() stream of int
    282 | 
    283 | let x = imitator.stream().map() { $0 + 1 } // use imitator stream
    284 | let y: Stream<Int> = ...
    285 | 
    286 | let m = Stream.merge(x, y) // merge imiator with other stream
    287 | 
    288 | imitator.imitate(m) // cycle all m up to imitator, this can only be done once
    289 | 
    290 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
    291 | // be used with care to not spin out of control.
    292 | 
    293 | 294 | See more 295 |
    296 |
    297 |

    Declaration

    298 |
    299 |

    Swift

    300 |
    public class Imitator<T>
    301 | 302 |
    303 |
    304 |
    305 |
    306 |
  • 307 |
308 |
309 |
310 |
311 | 315 |
316 |
317 | 318 | 319 | 320 | -------------------------------------------------------------------------------- /docs/Classes/Collector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Collector Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Collector

86 |
87 |
88 |
public class Collector<T>
89 | 90 |
91 |
92 |

Helper to collect values from a stream. Mainly useful for tests.

93 | 94 |
95 |
96 |
97 |
    98 |
  • 99 |
    100 | 101 | 102 | 103 | wait() 104 | 105 |
    106 |
    107 |
    108 |
    109 |
    110 |
    111 |

    Stall the thread and wait for the stream this collector works off to end.

    112 | 113 |
    114 |
    115 |

    Declaration

    116 |
    117 |

    Swift

    118 |
    public func wait() -> [T]
    119 | 120 |
    121 |
    122 |
    123 |
    124 |
  • 125 |
  • 126 |
    127 | 128 | 129 | 130 | take() 131 | 132 |
    133 |
    134 |
    135 |
    136 |
    137 |
    138 |

    Take whatever values are in the collector without waiting for 139 | the stream to end.

    140 | 141 |
    142 |
    143 |

    Declaration

    144 |
    145 |

    Swift

    146 |
    public func take() -> [T]
    147 | 148 |
    149 |
    150 |
    151 |
    152 |
  • 153 |
154 |
155 |
156 |
157 | 161 |
162 |
163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /docs/Classes/Imitator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Imitator Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Imitator

86 |
87 |
88 |
public class Imitator<T>
89 | 90 |
91 |
92 |

Imitators are used to create cyclic streams. The imitator is an originator 93 | of a stream at the same time as it imitates some other stream further down 94 | the code.

95 | 96 |

Here’s a bad idea illustrating the usage:

97 |
let imitator = Imitator<Int>() stream of int
 98 | 
 99 | let x = imitator.stream().map() { $0 + 1 } // use imitator stream
100 | let y: Stream<Int> = ...
101 | 
102 | let m = Stream.merge(x, y) // merge imiator with other stream
103 | 
104 | imitator.imitate(m) // cycle all m up to imitator, this can only be done once
105 | 
106 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
107 | // be used with care to not spin out of control.
108 | 
109 | 110 |
111 |
112 |
113 |
    114 |
  • 115 |
    116 | 117 | 118 | 119 | stream() 120 | 121 |
    122 |
    123 |
    124 |
    125 |
    126 |
    127 |

    Get a stream from this imitator. Can be used multiple times and each instance 128 | will be backed by the same imitator.

    129 | 130 |
    131 |
    132 |

    Declaration

    133 |
    134 |

    Swift

    135 |
    public func stream() -> Stream<T>
    136 | 137 |
    138 |
    139 |
    140 |
    141 |
  • 142 |
  • 143 |
    144 | 145 | 146 | 147 | imitate(other:) 148 | 149 |
    150 |
    151 |
    152 |
    153 |
    154 |
    155 |

    Start imitating another stream. This can be called exactly once. 156 | Repeated calls will fatalError.

    157 | 158 |
    159 |
    160 |

    Declaration

    161 |
    162 |

    Swift

    163 |
    public func imitate(other: Stream<T>)
    164 | 165 |
    166 |
    167 |
    168 |
    169 |
  • 170 |
171 |
172 |
173 |
174 | 178 |
179 |
180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /docs/Classes/Sink.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sink Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Sink

86 |
87 |
88 |
public class Sink<T>
89 | 90 |
91 |
92 |

The originator of a stream of values.

93 |
let sink = Sink<Int>()
 94 | 
 95 | let stream = sink.stream()
 96 | 
 97 | ...
 98 | sink.update(0)
 99 | sink.update(1)
100 | sink.end()
101 | 
102 | 103 |
104 |
105 |
106 |
    107 |
  • 108 |
    109 | 110 | 111 | 112 | init() 113 | 114 |
    115 |
    116 |
    117 |
    118 |
    119 |
    120 |

    Create a new sink.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public init()
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
  • 135 |
    136 | 137 | 138 | 139 | stream() 140 | 141 |
    142 |
    143 |
    144 |
    145 |
    146 |
    147 |

    Get a stream from this sink. Can be used multiple times and each instance 148 | will be backed by the same sink.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func stream() -> Stream<T>
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | update(_:) 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Update a value into the sink and all connected streams.

    176 | 177 |
    178 |
    179 |

    Declaration

    180 |
    181 |

    Swift

    182 |
    public func update(_ t: T)
    183 | 184 |
    185 |
    186 |
    187 |
    188 |
  • 189 |
  • 190 |
    191 | 192 | 193 | 194 | end() 195 | 196 |
    197 |
    198 |
    199 |
    200 |
    201 |
    202 |

    End this sink. No more values can be sent after this.

    203 | 204 |
    205 |
    206 |

    Declaration

    207 |
    208 |

    Swift

    209 |
    public func end()
    210 | 211 |
    212 |
    213 |
    214 |
    215 |
  • 216 |
217 |
218 |
219 |
220 | 224 |
225 |
226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /docs/Classes/Subscription.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Subscription Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Subscription

86 |
87 |
88 |
public class Subscription<T>
89 | 90 |
91 |
92 |

Subscriptions are receipts to the Stream.subscribe() operation. They 93 | can be used to unsubscribe.

94 |
let sink = Sink<Int>()
 95 | 
 96 | let sub = sink.stream().subscribe() { print("\($0)") }
 97 | 
 98 | sink.update(0)
 99 | sub.unsubscribe()
100 | sink.update(1) // not received
101 | 
102 | 103 |
104 |
105 |
106 |
    107 |
  • 108 |
    109 | 110 | 111 | 112 | unsubscribe() 113 | 114 |
    115 |
    116 |
    117 |
    118 |
    119 |
    120 |

    Unsubscribe from further updates.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public func unsubscribe()
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
135 |
136 |
137 |
138 | 142 |
143 |
144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | documentation 17 | 18 | 19 | documentation 20 | 21 | 22 | 100% 23 | 24 | 25 | 100% 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; 143 | white-space: nowrap; } 144 | .nav-group-task a { 145 | color: #888; } 146 | 147 | .main-content { 148 | background-color: #fff; 149 | border: 1px solid #e2e2e2; 150 | margin-left: 246px; 151 | position: absolute; 152 | overflow: hidden; 153 | padding-bottom: 20px; 154 | top: 70px; 155 | width: 734px; } 156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 157 | margin-bottom: 1em; } 158 | .main-content p { 159 | line-height: 1.8em; } 160 | .main-content section .section:first-child { 161 | margin-top: 0; 162 | padding-top: 0; } 163 | .main-content section .task-group-section .task-group:first-of-type { 164 | padding-top: 10px; } 165 | .main-content section .task-group-section .task-group:first-of-type .section-name { 166 | padding-top: 15px; } 167 | .main-content section .heading:before { 168 | content: ""; 169 | display: block; 170 | padding-top: 70px; 171 | margin: -70px 0 0; } 172 | 173 | .section { 174 | padding: 0 25px; } 175 | 176 | .highlight { 177 | background-color: #eee; 178 | padding: 10px 12px; 179 | border: 1px solid #e2e2e2; 180 | border-radius: 4px; 181 | overflow-x: auto; } 182 | 183 | .declaration .highlight { 184 | overflow-x: initial; 185 | padding: 0 40px 40px 0; 186 | margin-bottom: -25px; 187 | background-color: transparent; 188 | border: none; } 189 | 190 | .section-name { 191 | margin: 0; 192 | margin-left: 18px; } 193 | 194 | .task-group-section { 195 | padding-left: 6px; 196 | border-top: 1px solid #e2e2e2; } 197 | 198 | .task-group { 199 | padding-top: 0px; } 200 | 201 | .task-name-container a[name]:before { 202 | content: ""; 203 | display: block; 204 | padding-top: 70px; 205 | margin: -70px 0 0; } 206 | 207 | .item { 208 | padding-top: 8px; 209 | width: 100%; 210 | list-style-type: none; } 211 | .item a[name]:before { 212 | content: ""; 213 | display: block; 214 | padding-top: 70px; 215 | margin: -70px 0 0; } 216 | .item code { 217 | background-color: transparent; 218 | padding: 0; } 219 | .item .token, .item .direct-link { 220 | padding-left: 3px; 221 | margin-left: 15px; 222 | font-size: 11.9px; } 223 | .item .discouraged { 224 | text-decoration: line-through; } 225 | .item .declaration-note { 226 | font-size: .85em; 227 | color: gray; 228 | font-style: italic; } 229 | 230 | .pointer-container { 231 | border-bottom: 1px solid #e2e2e2; 232 | left: -23px; 233 | padding-bottom: 13px; 234 | position: relative; 235 | width: 110%; } 236 | 237 | .pointer { 238 | background: #f9f9f9; 239 | border-left: 1px solid #e2e2e2; 240 | border-top: 1px solid #e2e2e2; 241 | height: 12px; 242 | left: 21px; 243 | top: -7px; 244 | -webkit-transform: rotate(45deg); 245 | -moz-transform: rotate(45deg); 246 | -o-transform: rotate(45deg); 247 | transform: rotate(45deg); 248 | position: absolute; 249 | width: 12px; } 250 | 251 | .height-container { 252 | display: none; 253 | left: -25px; 254 | padding: 0 25px; 255 | position: relative; 256 | width: 100%; 257 | overflow: hidden; } 258 | .height-container .section { 259 | background: #f9f9f9; 260 | border-bottom: 1px solid #e2e2e2; 261 | left: -25px; 262 | position: relative; 263 | width: 100%; 264 | padding-top: 10px; 265 | padding-bottom: 5px; } 266 | 267 | .aside, .language { 268 | padding: 6px 12px; 269 | margin: 12px 0; 270 | border-left: 5px solid #dddddd; 271 | overflow-y: hidden; } 272 | .aside .aside-title, .language .aside-title { 273 | font-size: 9px; 274 | letter-spacing: 2px; 275 | text-transform: uppercase; 276 | padding-bottom: 0; 277 | margin: 0; 278 | color: #aaa; 279 | -webkit-user-select: none; } 280 | .aside p:last-child, .language p:last-child { 281 | margin-bottom: 0; } 282 | 283 | .language { 284 | border-left: 5px solid #cde9f4; } 285 | .language .aside-title { 286 | color: #4b8afb; } 287 | 288 | .aside-warning, .aside-deprecated, .aside-unavailable { 289 | border-left: 5px solid #ff6666; } 290 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { 291 | color: #ff0000; } 292 | 293 | .graybox { 294 | border-collapse: collapse; 295 | width: 100%; } 296 | .graybox p { 297 | margin: 0; 298 | word-break: break-word; 299 | min-width: 50px; } 300 | .graybox td { 301 | border: 1px solid #e2e2e2; 302 | padding: 5px 25px 5px 10px; 303 | vertical-align: middle; } 304 | .graybox tr td:first-of-type { 305 | text-align: right; 306 | padding: 7px; 307 | vertical-align: top; 308 | word-break: normal; 309 | width: 40px; } 310 | 311 | .slightly-smaller { 312 | font-size: 0.9em; } 313 | 314 | #footer { 315 | position: relative; 316 | top: 10px; 317 | bottom: 0px; 318 | margin-left: 25px; } 319 | #footer p { 320 | margin: 0; 321 | color: #aaa; 322 | font-size: 0.8em; } 323 | 324 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 325 | display: none; } 326 | html.dash .main-content { 327 | width: 980px; 328 | margin-left: 0; 329 | border: none; 330 | width: 100%; 331 | top: 0; 332 | padding-bottom: 0; } 333 | html.dash .height-container { 334 | display: block; } 335 | html.dash .item .token { 336 | margin-left: 0; } 337 | html.dash .content-wrapper { 338 | width: auto; } 339 | html.dash #footer { 340 | position: static; } 341 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | com.jazzy.froop 7 | CFBundleName 8 | froop 9 | DocSetPlatformFamily 10 | froop 11 | isDashDocset 12 | 13 | dashIndexFilePath 14 | index.html 15 | isJavaScriptEnabled 16 | 17 | DashDocSetFamily 18 | dashtoc 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/Classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Classes Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Classes

86 |

The following classes are available globally.

87 | 88 |
89 |
90 |
91 |
    92 |
  • 93 |
    94 | 95 | 96 | 97 | Stream 98 | 99 |
    100 |
    101 |
    102 |
    103 |
    104 |
    105 |

    Stream of vaules over time. Typically created by a Sink.

    106 |
    let sink = Sink<Int>()
    107 | 
    108 | let stream = sink.stream()
    109 | let double = stream.map() { $0 * 2 }
    110 | 
    111 | sink.update(0)
    112 | sink.update(1)
    113 | ...
    114 | 
    115 | 116 |

    For some detailed notes on how a combinator is structured for ARC and thread 117 | safety, see the source code for the .map() function. All operations follow 118 | a similar pattern.

    119 | 120 | See more 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public class Stream<T>
    127 | 128 |
    129 |
    130 |
    131 |
    132 |
  • 133 |
  • 134 |
    135 | 136 | 137 | 138 | MemoryStream 139 | 140 |
    141 |
    142 |
    143 |
    144 |
    145 |
    146 |

    Specialization of Stream that has memory. Memory means that any 147 | new listener added will straight away get the last value that went through the stream.

    148 | 149 |
    150 |
    151 |

    Declaration

    152 |
    153 |

    Swift

    154 |
    public class MemoryStream<T> : Stream<T>
    155 | 156 |
    157 |
    158 |
    159 |
    160 |
  • 161 |
  • 162 |
    163 | 164 | 165 | 166 | Sink 167 | 168 |
    169 |
    170 |
    171 |
    172 |
    173 |
    174 |

    The originator of a stream of values.

    175 |
    let sink = Sink<Int>()
    176 | 
    177 | let stream = sink.stream()
    178 | 
    179 | ...
    180 | sink.update(0)
    181 | sink.update(1)
    182 | sink.end()
    183 | 
    184 | 185 | See more 186 |
    187 |
    188 |

    Declaration

    189 |
    190 |

    Swift

    191 |
    public class Sink<T>
    192 | 193 |
    194 |
    195 |
    196 |
    197 |
  • 198 |
  • 199 |
    200 | 201 | 202 | 203 | Collector 204 | 205 |
    206 |
    207 |
    208 |
    209 |
    210 |
    211 |

    Helper to collect values from a stream. Mainly useful for tests.

    212 | 213 | See more 214 |
    215 |
    216 |

    Declaration

    217 |
    218 |

    Swift

    219 |
    public class Collector<T>
    220 | 221 |
    222 |
    223 |
    224 |
    225 |
  • 226 |
  • 227 |
    228 | 229 | 230 | 231 | Subscription 232 | 233 |
    234 |
    235 |
    236 |
    237 |
    238 |
    239 |

    Subscriptions are receipts to the Stream.subscribe() operation. They 240 | can be used to unsubscribe.

    241 |
    let sink = Sink<Int>()
    242 | 
    243 | let sub = sink.stream().subscribe() { print("\($0)") }
    244 | 
    245 | sink.update(0)
    246 | sub.unsubscribe()
    247 | sink.update(1) // not received
    248 | 
    249 | 250 | See more 251 |
    252 |
    253 |

    Declaration

    254 |
    255 |

    Swift

    256 |
    public class Subscription<T>
    257 | 258 |
    259 |
    260 |
    261 |
    262 |
  • 263 |
  • 264 |
    265 | 266 | 267 | 268 | Imitator 269 | 270 |
    271 |
    272 |
    273 |
    274 |
    275 |
    276 |

    Imitators are used to create cyclic streams. The imitator is an originator 277 | of a stream at the same time as it imitates some other stream further down 278 | the code.

    279 | 280 |

    Here’s a bad idea illustrating the usage:

    281 |
    let imitator = Imitator<Int>() stream of int
    282 | 
    283 | let x = imitator.stream().map() { $0 + 1 } // use imitator stream
    284 | let y: Stream<Int> = ...
    285 | 
    286 | let m = Stream.merge(x, y) // merge imiator with other stream
    287 | 
    288 | imitator.imitate(m) // cycle all m up to imitator, this can only be done once
    289 | 
    290 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
    291 | // be used with care to not spin out of control.
    292 | 
    293 | 294 | See more 295 |
    296 |
    297 |

    Declaration

    298 |
    299 |

    Swift

    300 |
    public class Imitator<T>
    301 | 302 |
    303 |
    304 |
    305 |
    306 |
  • 307 |
308 |
309 |
310 |
311 | 315 |
316 |
317 | 318 | 319 | 320 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Collector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Collector Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Collector

86 |
87 |
88 |
public class Collector<T>
89 | 90 |
91 |
92 |

Helper to collect values from a stream. Mainly useful for tests.

93 | 94 |
95 |
96 |
97 |
    98 |
  • 99 |
    100 | 101 | 102 | 103 | wait() 104 | 105 |
    106 |
    107 |
    108 |
    109 |
    110 |
    111 |

    Stall the thread and wait for the stream this collector works off to end.

    112 | 113 |
    114 |
    115 |

    Declaration

    116 |
    117 |

    Swift

    118 |
    public func wait() -> [T]
    119 | 120 |
    121 |
    122 |
    123 |
    124 |
  • 125 |
  • 126 |
    127 | 128 | 129 | 130 | take() 131 | 132 |
    133 |
    134 |
    135 |
    136 |
    137 |
    138 |

    Take whatever values are in the collector without waiting for 139 | the stream to end.

    140 | 141 |
    142 |
    143 |

    Declaration

    144 |
    145 |

    Swift

    146 |
    public func take() -> [T]
    147 | 148 |
    149 |
    150 |
    151 |
    152 |
  • 153 |
154 |
155 |
156 |
157 | 161 |
162 |
163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Imitator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Imitator Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Imitator

86 |
87 |
88 |
public class Imitator<T>
89 | 90 |
91 |
92 |

Imitators are used to create cyclic streams. The imitator is an originator 93 | of a stream at the same time as it imitates some other stream further down 94 | the code.

95 | 96 |

Here’s a bad idea illustrating the usage:

97 |
let imitator = Imitator<Int>() stream of int
 98 | 
 99 | let x = imitator.stream().map() { $0 + 1 } // use imitator stream
100 | let y: Stream<Int> = ...
101 | 
102 | let m = Stream.merge(x, y) // merge imiator with other stream
103 | 
104 | imitator.imitate(m) // cycle all m up to imitator, this can only be done once
105 | 
106 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
107 | // be used with care to not spin out of control.
108 | 
109 | 110 |
111 |
112 |
113 |
    114 |
  • 115 |
    116 | 117 | 118 | 119 | stream() 120 | 121 |
    122 |
    123 |
    124 |
    125 |
    126 |
    127 |

    Get a stream from this imitator. Can be used multiple times and each instance 128 | will be backed by the same imitator.

    129 | 130 |
    131 |
    132 |

    Declaration

    133 |
    134 |

    Swift

    135 |
    public func stream() -> Stream<T>
    136 | 137 |
    138 |
    139 |
    140 |
    141 |
  • 142 |
  • 143 |
    144 | 145 | 146 | 147 | imitate(other:) 148 | 149 |
    150 |
    151 |
    152 |
    153 |
    154 |
    155 |

    Start imitating another stream. This can be called exactly once. 156 | Repeated calls will fatalError.

    157 | 158 |
    159 |
    160 |

    Declaration

    161 |
    162 |

    Swift

    163 |
    public func imitate(other: Stream<T>)
    164 | 165 |
    166 |
    167 |
    168 |
    169 |
  • 170 |
171 |
172 |
173 |
174 | 178 |
179 |
180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Sink.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sink Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Sink

86 |
87 |
88 |
public class Sink<T>
89 | 90 |
91 |
92 |

The originator of a stream of values.

93 |
let sink = Sink<Int>()
 94 | 
 95 | let stream = sink.stream()
 96 | 
 97 | ...
 98 | sink.update(0)
 99 | sink.update(1)
100 | sink.end()
101 | 
102 | 103 |
104 |
105 |
106 |
    107 |
  • 108 |
    109 | 110 | 111 | 112 | init() 113 | 114 |
    115 |
    116 |
    117 |
    118 |
    119 |
    120 |

    Create a new sink.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public init()
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
  • 135 |
    136 | 137 | 138 | 139 | stream() 140 | 141 |
    142 |
    143 |
    144 |
    145 |
    146 |
    147 |

    Get a stream from this sink. Can be used multiple times and each instance 148 | will be backed by the same sink.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func stream() -> Stream<T>
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | update(_:) 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Update a value into the sink and all connected streams.

    176 | 177 |
    178 |
    179 |

    Declaration

    180 |
    181 |

    Swift

    182 |
    public func update(_ t: T)
    183 | 184 |
    185 |
    186 |
    187 |
    188 |
  • 189 |
  • 190 |
    191 | 192 | 193 | 194 | end() 195 | 196 |
    197 |
    198 |
    199 |
    200 |
    201 |
    202 |

    End this sink. No more values can be sent after this.

    203 | 204 |
    205 |
    206 |

    Declaration

    207 |
    208 |

    Swift

    209 |
    public func end()
    210 | 211 |
    212 |
    213 |
    214 |
    215 |
  • 216 |
217 |
218 |
219 |
220 | 224 |
225 |
226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Subscription.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Subscription Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

froop Docs (100% documented)

18 |

View on GitHub

19 |
20 |
21 |
22 | 27 |
28 |
29 | 82 |
83 |
84 |
85 |

Subscription

86 |
87 |
88 |
public class Subscription<T>
89 | 90 |
91 |
92 |

Subscriptions are receipts to the Stream.subscribe() operation. They 93 | can be used to unsubscribe.

94 |
let sink = Sink<Int>()
 95 | 
 96 | let sub = sink.stream().subscribe() { print("\($0)") }
 97 | 
 98 | sink.update(0)
 99 | sub.unsubscribe()
100 | sink.update(1) // not received
101 | 
102 | 103 |
104 |
105 |
106 |
    107 |
  • 108 |
    109 | 110 | 111 | 112 | unsubscribe() 113 | 114 |
    115 |
    116 |
    117 |
    118 |
    119 |
    120 |

    Unsubscribe from further updates.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public func unsubscribe()
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
135 |
136 |
137 |
138 | 142 |
143 |
144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; 143 | white-space: nowrap; } 144 | .nav-group-task a { 145 | color: #888; } 146 | 147 | .main-content { 148 | background-color: #fff; 149 | border: 1px solid #e2e2e2; 150 | margin-left: 246px; 151 | position: absolute; 152 | overflow: hidden; 153 | padding-bottom: 20px; 154 | top: 70px; 155 | width: 734px; } 156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 157 | margin-bottom: 1em; } 158 | .main-content p { 159 | line-height: 1.8em; } 160 | .main-content section .section:first-child { 161 | margin-top: 0; 162 | padding-top: 0; } 163 | .main-content section .task-group-section .task-group:first-of-type { 164 | padding-top: 10px; } 165 | .main-content section .task-group-section .task-group:first-of-type .section-name { 166 | padding-top: 15px; } 167 | .main-content section .heading:before { 168 | content: ""; 169 | display: block; 170 | padding-top: 70px; 171 | margin: -70px 0 0; } 172 | 173 | .section { 174 | padding: 0 25px; } 175 | 176 | .highlight { 177 | background-color: #eee; 178 | padding: 10px 12px; 179 | border: 1px solid #e2e2e2; 180 | border-radius: 4px; 181 | overflow-x: auto; } 182 | 183 | .declaration .highlight { 184 | overflow-x: initial; 185 | padding: 0 40px 40px 0; 186 | margin-bottom: -25px; 187 | background-color: transparent; 188 | border: none; } 189 | 190 | .section-name { 191 | margin: 0; 192 | margin-left: 18px; } 193 | 194 | .task-group-section { 195 | padding-left: 6px; 196 | border-top: 1px solid #e2e2e2; } 197 | 198 | .task-group { 199 | padding-top: 0px; } 200 | 201 | .task-name-container a[name]:before { 202 | content: ""; 203 | display: block; 204 | padding-top: 70px; 205 | margin: -70px 0 0; } 206 | 207 | .item { 208 | padding-top: 8px; 209 | width: 100%; 210 | list-style-type: none; } 211 | .item a[name]:before { 212 | content: ""; 213 | display: block; 214 | padding-top: 70px; 215 | margin: -70px 0 0; } 216 | .item code { 217 | background-color: transparent; 218 | padding: 0; } 219 | .item .token, .item .direct-link { 220 | padding-left: 3px; 221 | margin-left: 15px; 222 | font-size: 11.9px; } 223 | .item .discouraged { 224 | text-decoration: line-through; } 225 | .item .declaration-note { 226 | font-size: .85em; 227 | color: gray; 228 | font-style: italic; } 229 | 230 | .pointer-container { 231 | border-bottom: 1px solid #e2e2e2; 232 | left: -23px; 233 | padding-bottom: 13px; 234 | position: relative; 235 | width: 110%; } 236 | 237 | .pointer { 238 | background: #f9f9f9; 239 | border-left: 1px solid #e2e2e2; 240 | border-top: 1px solid #e2e2e2; 241 | height: 12px; 242 | left: 21px; 243 | top: -7px; 244 | -webkit-transform: rotate(45deg); 245 | -moz-transform: rotate(45deg); 246 | -o-transform: rotate(45deg); 247 | transform: rotate(45deg); 248 | position: absolute; 249 | width: 12px; } 250 | 251 | .height-container { 252 | display: none; 253 | left: -25px; 254 | padding: 0 25px; 255 | position: relative; 256 | width: 100%; 257 | overflow: hidden; } 258 | .height-container .section { 259 | background: #f9f9f9; 260 | border-bottom: 1px solid #e2e2e2; 261 | left: -25px; 262 | position: relative; 263 | width: 100%; 264 | padding-top: 10px; 265 | padding-bottom: 5px; } 266 | 267 | .aside, .language { 268 | padding: 6px 12px; 269 | margin: 12px 0; 270 | border-left: 5px solid #dddddd; 271 | overflow-y: hidden; } 272 | .aside .aside-title, .language .aside-title { 273 | font-size: 9px; 274 | letter-spacing: 2px; 275 | text-transform: uppercase; 276 | padding-bottom: 0; 277 | margin: 0; 278 | color: #aaa; 279 | -webkit-user-select: none; } 280 | .aside p:last-child, .language p:last-child { 281 | margin-bottom: 0; } 282 | 283 | .language { 284 | border-left: 5px solid #cde9f4; } 285 | .language .aside-title { 286 | color: #4b8afb; } 287 | 288 | .aside-warning, .aside-deprecated, .aside-unavailable { 289 | border-left: 5px solid #ff6666; } 290 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { 291 | color: #ff0000; } 292 | 293 | .graybox { 294 | border-collapse: collapse; 295 | width: 100%; } 296 | .graybox p { 297 | margin: 0; 298 | word-break: break-word; 299 | min-width: 50px; } 300 | .graybox td { 301 | border: 1px solid #e2e2e2; 302 | padding: 5px 25px 5px 10px; 303 | vertical-align: middle; } 304 | .graybox tr td:first-of-type { 305 | text-align: right; 306 | padding: 7px; 307 | vertical-align: top; 308 | word-break: normal; 309 | width: 40px; } 310 | 311 | .slightly-smaller { 312 | font-size: 0.9em; } 313 | 314 | #footer { 315 | position: relative; 316 | top: 10px; 317 | bottom: 0px; 318 | margin-left: 25px; } 319 | #footer p { 320 | margin: 0; 321 | color: #aaa; 322 | font-size: 0.8em; } 323 | 324 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 325 | display: none; } 326 | html.dash .main-content { 327 | width: 980px; 328 | margin-left: 0; 329 | border: none; 330 | width: 100%; 331 | top: 0; 332 | padding-bottom: 0; } 333 | html.dash .height-container { 334 | display: block; } 335 | html.dash .item .token { 336 | margin-left: 0; } 337 | html.dash .content-wrapper { 338 | width: auto; } 339 | html.dash #footer { 340 | position: static; } 341 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/Documents/img/carat.png -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/Documents/img/dash.png -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/Documents/img/gh.png -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | froop Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

froop Docs (100% documented)

17 |

View on GitHub

18 |
19 |
20 |
21 | 26 |
27 |
28 | 81 |
82 |
83 |
84 | 85 |

froop

86 |

Authors

87 | 88 |

Lookback

89 | 90 |
91 |
92 | 96 |
97 |
98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | 42 | // Dumb down quotes within code blocks that delimit strings instead of quotations 43 | // https://github.com/realm/jazzy/issues/714 44 | $("code q").replaceWith(function () { 45 | return ["\"", $(this).contents(), "\""]; 46 | }); 47 | -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/Documents/search.json: -------------------------------------------------------------------------------- 1 | {"Functions.html#/s:5froop7flatten6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flatten(nested:)","abstract":"

Flatten a stream of streams, sequentially. This means that any new stream"},"Functions.html#/s:5froop19flattenConcurrently6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flattenConcurrently(nested:)","abstract":"

Flatten a stream of streams, concurrently. This means that any new stream"},"Functions.html#/s:5froop5mergeyAA6StreamCyxGAEd_tlF":{"name":"merge(_:)","abstract":"

Merge a bunch of streams emitting the same T to one.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_tGADyxG_ADyq_Gtr0_lF":{"name":"combine(_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_tGADyxG_ADyq_GADyq0_Gtr1_lF":{"name":"combine(_:_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_tGADyxG_ADyq_GADyq0_GADyq1_Gtr2_lF":{"name":"combine(_:_:_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_q2_tGADyxG_ADyq_GADyq0_GADyq1_GADyq2_Gtr3_lF":{"name":"combine(_:_:_:_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Classes/Imitator.html#/s:5froop8ImitatorC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"

Get a stream from this imitator. Can be used multiple times and each instance","parent_name":"Imitator"},"Classes/Imitator.html#/s:5froop8ImitatorC7imitate5otheryAA6StreamCyxG_tF":{"name":"imitate(other:)","abstract":"

Start imitating another stream. This can be called exactly once.","parent_name":"Imitator"},"Classes/Subscription.html#/s:5froop12SubscriptionC11unsubscribeyyF":{"name":"unsubscribe()","abstract":"

Unsubscribe from further updates.

","parent_name":"Subscription"},"Classes/Collector.html#/s:5froop9CollectorC4waitSayxGyF":{"name":"wait()","abstract":"

Stall the thread and wait for the stream this collector works off to end.

","parent_name":"Collector"},"Classes/Collector.html#/s:5froop9CollectorC4takeSayxGyF":{"name":"take()","abstract":"

Take whatever values are in the collector without waiting for","parent_name":"Collector"},"Classes/Sink.html#/s:5froop4SinkCACyxGycfc":{"name":"init()","abstract":"

Create a new sink.

","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"

Get a stream from this sink. Can be used multiple times and each instance","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6updateyyxF":{"name":"update(_:)","abstract":"

Update a value into the sink and all connected streams.

","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC3endyyF":{"name":"end()","abstract":"

End this sink. No more values can be sent after this.

","parent_name":"Sink"},"Classes/Stream.html#/s:5froop6StreamC9subscribeyAA12SubscriptionCyxGyxSgcF":{"name":"subscribe(_:)","abstract":"

Subscribe to values from this stream. Nil indicates the end of","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7collectAA9CollectorCyxGyF":{"name":"collect()","abstract":"

Collect values of this stream into an array of values.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8dedupeByyACyxGqd__xcSQRd__lF":{"name":"dedupeBy(_:)","abstract":"

Dedupe the stream by extracting some equatable value from it.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4drop6amountACyxGSu_tF":{"name":"drop(amount:)","abstract":"

Drop a fixed number of initial values, then start emitting.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9dropWhileyACyxGSbxcF":{"name":"dropWhile(_:)","abstract":"

Drop values while some condition holds true, then start emitting.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7endWhen5otherACyxGACyqd__G_tlF":{"name":"endWhen(other:)","abstract":"

Make a stream that ends when some other stream ends.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC6filteryACyxGSbxcF":{"name":"filter(_:)","abstract":"

Filter the stream using some sort of test.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4foldyAA06MemoryB0Cyqd__Gqd___qd__qd___xtctlF":{"name":"fold(_:_:)","abstract":"

Fold the stream by combining values from the past with the new value.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4lastACyxGyF":{"name":"last()","abstract":"

Makes a stream that only emits the last value.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC3mapyACyqd__Gqd__xclF":{"name":"map(_:)","abstract":"

Transform values of type T to type U.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC5mapTo5valueACyqd__Gqd___tlF":{"name":"mapTo(value:)","abstract":"

Transform any incoming value to one fixed value.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8rememberAA06MemoryB0CyxGyF":{"name":"remember()","abstract":"

Make a stream that remembers the last value. Any new (or combinator) will get the","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC13sampleCombineyACyx_qd__tGACyqd__GlF":{"name":"sampleCombine(_:)","abstract":"

For every value of this stream, take a sample of the last value of some other","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9startWith5valueAA06MemoryB0CyxGx_tF":{"name":"startWith(value:)","abstract":"

Prepend a value to a stream. Or in other words, give a start value to a stream.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4take6amountACyxGSu_tF":{"name":"take(amount:)","abstract":"

Take a fixed amount of elements, then end.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9takeWhileyACyxGSbxcF":{"name":"takeWhile(_:)","abstract":"

Take values from the stream while some condition hold true, then end the stream.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4waityyF":{"name":"wait()","abstract":"

Stall the thread until the stream to ends.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamCAASQRzlE6dedupeACyxGyF":{"name":"dedupe()","abstract":"

Dedupe the stream by the value in the stream itself

","parent_name":"Stream"},"Classes/Stream.html":{"name":"Stream","abstract":"

Stream of vaules over time. Typically created by a Sink.

"},"Classes.html#/s:5froop12MemoryStreamC":{"name":"MemoryStream","abstract":"

Specialization of Stream that has memory. Memory means that any"},"Classes/Sink.html":{"name":"Sink","abstract":"

The originator of a stream of values.

"},"Classes/Collector.html":{"name":"Collector","abstract":"

Helper to collect values from a stream. Mainly useful for tests.

"},"Classes/Subscription.html":{"name":"Subscription","abstract":"

Subscriptions are receipts to the Stream.subscribe() operation. They"},"Classes/Imitator.html":{"name":"Imitator","abstract":"

Imitators are used to create cyclic streams. The imitator is an originator"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Functions.html":{"name":"Functions","abstract":"

The following functions are available globally.

"}} -------------------------------------------------------------------------------- /docs/docsets/froop.docset/Contents/Resources/docSet.dsidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/docSet.dsidx -------------------------------------------------------------------------------- /docs/docsets/froop.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.tgz -------------------------------------------------------------------------------- /docs/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/img/carat.png -------------------------------------------------------------------------------- /docs/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/img/dash.png -------------------------------------------------------------------------------- /docs/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/img/gh.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | froop Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

froop Docs (100% documented)

17 |

View on GitHub

18 |
19 |
20 |
21 | 26 |
27 |
28 | 81 |
82 |
83 |
84 | 85 |

froop

86 |

Authors

87 | 88 |

Lookback

89 | 90 |
91 |
92 | 96 |
97 |
98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | 42 | // Dumb down quotes within code blocks that delimit strings instead of quotations 43 | // https://github.com/realm/jazzy/issues/714 44 | $("code q").replaceWith(function () { 45 | return ["\"", $(this).contents(), "\""]; 46 | }); 47 | -------------------------------------------------------------------------------- /docs/search.json: -------------------------------------------------------------------------------- 1 | {"Functions.html#/s:5froop7flatten6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flatten(nested:)","abstract":"

Flatten a stream of streams, sequentially. This means that any new stream"},"Functions.html#/s:5froop19flattenConcurrently6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flattenConcurrently(nested:)","abstract":"

Flatten a stream of streams, concurrently. This means that any new stream"},"Functions.html#/s:5froop5mergeyAA6StreamCyxGAEd_tlF":{"name":"merge(_:)","abstract":"

Merge a bunch of streams emitting the same T to one.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_tGADyxG_ADyq_Gtr0_lF":{"name":"combine(_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_tGADyxG_ADyq_GADyq0_Gtr1_lF":{"name":"combine(_:_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_tGADyxG_ADyq_GADyq0_GADyq1_Gtr2_lF":{"name":"combine(_:_:_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_q2_tGADyxG_ADyq_GADyq0_GADyq1_GADyq2_Gtr3_lF":{"name":"combine(_:_:_:_:_:)","abstract":"

Combine a number of streams and emit values when any of them emit a value.

"},"Classes/Imitator.html#/s:5froop8ImitatorC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"

Get a stream from this imitator. Can be used multiple times and each instance","parent_name":"Imitator"},"Classes/Imitator.html#/s:5froop8ImitatorC7imitate5otheryAA6StreamCyxG_tF":{"name":"imitate(other:)","abstract":"

Start imitating another stream. This can be called exactly once.","parent_name":"Imitator"},"Classes/Subscription.html#/s:5froop12SubscriptionC11unsubscribeyyF":{"name":"unsubscribe()","abstract":"

Unsubscribe from further updates.

","parent_name":"Subscription"},"Classes/Collector.html#/s:5froop9CollectorC4waitSayxGyF":{"name":"wait()","abstract":"

Stall the thread and wait for the stream this collector works off to end.

","parent_name":"Collector"},"Classes/Collector.html#/s:5froop9CollectorC4takeSayxGyF":{"name":"take()","abstract":"

Take whatever values are in the collector without waiting for","parent_name":"Collector"},"Classes/Sink.html#/s:5froop4SinkCACyxGycfc":{"name":"init()","abstract":"

Create a new sink.

","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"

Get a stream from this sink. Can be used multiple times and each instance","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6updateyyxF":{"name":"update(_:)","abstract":"

Update a value into the sink and all connected streams.

","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC3endyyF":{"name":"end()","abstract":"

End this sink. No more values can be sent after this.

","parent_name":"Sink"},"Classes/Stream.html#/s:5froop6StreamC9subscribeyAA12SubscriptionCyxGyxSgcF":{"name":"subscribe(_:)","abstract":"

Subscribe to values from this stream. Nil indicates the end of","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7collectAA9CollectorCyxGyF":{"name":"collect()","abstract":"

Collect values of this stream into an array of values.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8dedupeByyACyxGqd__xcSQRd__lF":{"name":"dedupeBy(_:)","abstract":"

Dedupe the stream by extracting some equatable value from it.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4drop6amountACyxGSu_tF":{"name":"drop(amount:)","abstract":"

Drop a fixed number of initial values, then start emitting.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9dropWhileyACyxGSbxcF":{"name":"dropWhile(_:)","abstract":"

Drop values while some condition holds true, then start emitting.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7endWhen5otherACyxGACyqd__G_tlF":{"name":"endWhen(other:)","abstract":"

Make a stream that ends when some other stream ends.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC6filteryACyxGSbxcF":{"name":"filter(_:)","abstract":"

Filter the stream using some sort of test.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4foldyAA06MemoryB0Cyqd__Gqd___qd__qd___xtctlF":{"name":"fold(_:_:)","abstract":"

Fold the stream by combining values from the past with the new value.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4lastACyxGyF":{"name":"last()","abstract":"

Makes a stream that only emits the last value.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC3mapyACyqd__Gqd__xclF":{"name":"map(_:)","abstract":"

Transform values of type T to type U.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC5mapTo5valueACyqd__Gqd___tlF":{"name":"mapTo(value:)","abstract":"

Transform any incoming value to one fixed value.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8rememberAA06MemoryB0CyxGyF":{"name":"remember()","abstract":"

Make a stream that remembers the last value. Any new (or combinator) will get the","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC13sampleCombineyACyx_qd__tGACyqd__GlF":{"name":"sampleCombine(_:)","abstract":"

For every value of this stream, take a sample of the last value of some other","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9startWith5valueAA06MemoryB0CyxGx_tF":{"name":"startWith(value:)","abstract":"

Prepend a value to a stream. Or in other words, give a start value to a stream.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4take6amountACyxGSu_tF":{"name":"take(amount:)","abstract":"

Take a fixed amount of elements, then end.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9takeWhileyACyxGSbxcF":{"name":"takeWhile(_:)","abstract":"

Take values from the stream while some condition hold true, then end the stream.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4waityyF":{"name":"wait()","abstract":"

Stall the thread until the stream to ends.

","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamCAASQRzlE6dedupeACyxGyF":{"name":"dedupe()","abstract":"

Dedupe the stream by the value in the stream itself

","parent_name":"Stream"},"Classes/Stream.html":{"name":"Stream","abstract":"

Stream of vaules over time. Typically created by a Sink.

"},"Classes.html#/s:5froop12MemoryStreamC":{"name":"MemoryStream","abstract":"

Specialization of Stream that has memory. Memory means that any"},"Classes/Sink.html":{"name":"Sink","abstract":"

The originator of a stream of values.

"},"Classes/Collector.html":{"name":"Collector","abstract":"

Helper to collect values from a stream. Mainly useful for tests.

"},"Classes/Subscription.html":{"name":"Subscription","abstract":"

Subscriptions are receipts to the Stream.subscribe() operation. They"},"Classes/Imitator.html":{"name":"Imitator","abstract":"

Imitators are used to create cyclic streams. The imitator is an originator"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Functions.html":{"name":"Functions","abstract":"

The following functions are available globally.

"}} -------------------------------------------------------------------------------- /docs/undocumented.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": [ 3 | 4 | ], 5 | "source_directory": "/Users/martin/Desktop/froop" 6 | } -------------------------------------------------------------------------------- /froop.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5B891BFF2222EC47002F31C6 /* froop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B891BF52222EC46002F31C6 /* froop.framework */; }; 11 | 5B891C042222EC47002F31C6 /* froopTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B891C032222EC47002F31C6 /* froopTests.swift */; }; 12 | 5B891C062222EC47002F31C6 /* froop.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B891BF82222EC46002F31C6 /* froop.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 5B891C102222EC5D002F31C6 /* froop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B891C0F2222EC5D002F31C6 /* froop.swift */; }; 14 | 5B891C122222ECC1002F31C6 /* Threadly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B891C112222ECC1002F31C6 /* Threadly.swift */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXContainerItemProxy section */ 18 | 5B891C002222EC47002F31C6 /* PBXContainerItemProxy */ = { 19 | isa = PBXContainerItemProxy; 20 | containerPortal = 5B891BEC2222EC46002F31C6 /* Project object */; 21 | proxyType = 1; 22 | remoteGlobalIDString = 5B891BF42222EC46002F31C6; 23 | remoteInfo = froop; 24 | }; 25 | /* End PBXContainerItemProxy section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 5B891BF52222EC46002F31C6 /* froop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = froop.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 5B891BF82222EC46002F31C6 /* froop.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = froop.h; sourceTree = ""; }; 30 | 5B891BF92222EC46002F31C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 5B891BFE2222EC47002F31C6 /* froopTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = froopTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 5B891C032222EC47002F31C6 /* froopTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = froopTests.swift; sourceTree = ""; }; 33 | 5B891C052222EC47002F31C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 5B891C0F2222EC5D002F31C6 /* froop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = froop.swift; sourceTree = ""; }; 35 | 5B891C112222ECC1002F31C6 /* Threadly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Threadly.swift; sourceTree = ""; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | 5B891BF22222EC46002F31C6 /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | 5B891BFB2222EC47002F31C6 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | 5B891BFF2222EC47002F31C6 /* froop.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 5B891BEB2222EC46002F31C6 = { 58 | isa = PBXGroup; 59 | children = ( 60 | 5B891BF72222EC46002F31C6 /* froop */, 61 | 5B891C022222EC47002F31C6 /* froopTests */, 62 | 5B891BF62222EC46002F31C6 /* Products */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | 5B891BF62222EC46002F31C6 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 5B891BF52222EC46002F31C6 /* froop.framework */, 70 | 5B891BFE2222EC47002F31C6 /* froopTests.xctest */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | 5B891BF72222EC46002F31C6 /* froop */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 5B891BF82222EC46002F31C6 /* froop.h */, 79 | 5B891C0F2222EC5D002F31C6 /* froop.swift */, 80 | 5B891BF92222EC46002F31C6 /* Info.plist */, 81 | 5B891C112222ECC1002F31C6 /* Threadly.swift */, 82 | ); 83 | path = froop; 84 | sourceTree = ""; 85 | }; 86 | 5B891C022222EC47002F31C6 /* froopTests */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 5B891C032222EC47002F31C6 /* froopTests.swift */, 90 | 5B891C052222EC47002F31C6 /* Info.plist */, 91 | ); 92 | path = froopTests; 93 | sourceTree = ""; 94 | }; 95 | /* End PBXGroup section */ 96 | 97 | /* Begin PBXHeadersBuildPhase section */ 98 | 5B891BF02222EC46002F31C6 /* Headers */ = { 99 | isa = PBXHeadersBuildPhase; 100 | buildActionMask = 2147483647; 101 | files = ( 102 | 5B891C062222EC47002F31C6 /* froop.h in Headers */, 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | /* End PBXHeadersBuildPhase section */ 107 | 108 | /* Begin PBXNativeTarget section */ 109 | 5B891BF42222EC46002F31C6 /* froop */ = { 110 | isa = PBXNativeTarget; 111 | buildConfigurationList = 5B891C092222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froop" */; 112 | buildPhases = ( 113 | 5B891BF02222EC46002F31C6 /* Headers */, 114 | 5B891BF12222EC46002F31C6 /* Sources */, 115 | 5B891BF22222EC46002F31C6 /* Frameworks */, 116 | 5B891BF32222EC46002F31C6 /* Resources */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = froop; 123 | productName = froop; 124 | productReference = 5B891BF52222EC46002F31C6 /* froop.framework */; 125 | productType = "com.apple.product-type.framework"; 126 | }; 127 | 5B891BFD2222EC47002F31C6 /* froopTests */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 5B891C0C2222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froopTests" */; 130 | buildPhases = ( 131 | 5B891BFA2222EC47002F31C6 /* Sources */, 132 | 5B891BFB2222EC47002F31C6 /* Frameworks */, 133 | 5B891BFC2222EC47002F31C6 /* Resources */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | 5B891C012222EC47002F31C6 /* PBXTargetDependency */, 139 | ); 140 | name = froopTests; 141 | productName = froopTests; 142 | productReference = 5B891BFE2222EC47002F31C6 /* froopTests.xctest */; 143 | productType = "com.apple.product-type.bundle.unit-test"; 144 | }; 145 | /* End PBXNativeTarget section */ 146 | 147 | /* Begin PBXProject section */ 148 | 5B891BEC2222EC46002F31C6 /* Project object */ = { 149 | isa = PBXProject; 150 | attributes = { 151 | LastSwiftUpdateCheck = 1010; 152 | LastUpgradeCheck = 1250; 153 | ORGANIZATIONNAME = "Lookback Ltd"; 154 | TargetAttributes = { 155 | 5B891BF42222EC46002F31C6 = { 156 | CreatedOnToolsVersion = 10.1; 157 | LastSwiftMigration = 1020; 158 | }; 159 | 5B891BFD2222EC47002F31C6 = { 160 | CreatedOnToolsVersion = 10.1; 161 | LastSwiftMigration = 1020; 162 | }; 163 | }; 164 | }; 165 | buildConfigurationList = 5B891BEF2222EC46002F31C6 /* Build configuration list for PBXProject "froop" */; 166 | compatibilityVersion = "Xcode 9.3"; 167 | developmentRegion = en; 168 | hasScannedForEncodings = 0; 169 | knownRegions = ( 170 | en, 171 | Base, 172 | ); 173 | mainGroup = 5B891BEB2222EC46002F31C6; 174 | productRefGroup = 5B891BF62222EC46002F31C6 /* Products */; 175 | projectDirPath = ""; 176 | projectRoot = ""; 177 | targets = ( 178 | 5B891BF42222EC46002F31C6 /* froop */, 179 | 5B891BFD2222EC47002F31C6 /* froopTests */, 180 | ); 181 | }; 182 | /* End PBXProject section */ 183 | 184 | /* Begin PBXResourcesBuildPhase section */ 185 | 5B891BF32222EC46002F31C6 /* Resources */ = { 186 | isa = PBXResourcesBuildPhase; 187 | buildActionMask = 2147483647; 188 | files = ( 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | 5B891BFC2222EC47002F31C6 /* Resources */ = { 193 | isa = PBXResourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | }; 199 | /* End PBXResourcesBuildPhase section */ 200 | 201 | /* Begin PBXSourcesBuildPhase section */ 202 | 5B891BF12222EC46002F31C6 /* Sources */ = { 203 | isa = PBXSourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | 5B891C122222ECC1002F31C6 /* Threadly.swift in Sources */, 207 | 5B891C102222EC5D002F31C6 /* froop.swift in Sources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | 5B891BFA2222EC47002F31C6 /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 5B891C042222EC47002F31C6 /* froopTests.swift in Sources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXSourcesBuildPhase section */ 220 | 221 | /* Begin PBXTargetDependency section */ 222 | 5B891C012222EC47002F31C6 /* PBXTargetDependency */ = { 223 | isa = PBXTargetDependency; 224 | target = 5B891BF42222EC46002F31C6 /* froop */; 225 | targetProxy = 5B891C002222EC47002F31C6 /* PBXContainerItemProxy */; 226 | }; 227 | /* End PBXTargetDependency section */ 228 | 229 | /* Begin XCBuildConfiguration section */ 230 | 5B891C072222EC47002F31C6 /* Debug */ = { 231 | isa = XCBuildConfiguration; 232 | buildSettings = { 233 | ALWAYS_SEARCH_USER_PATHS = NO; 234 | CLANG_ANALYZER_NONNULL = YES; 235 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 236 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 237 | CLANG_CXX_LIBRARY = "libc++"; 238 | CLANG_ENABLE_MODULES = YES; 239 | CLANG_ENABLE_OBJC_ARC = YES; 240 | CLANG_ENABLE_OBJC_WEAK = YES; 241 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 242 | CLANG_WARN_BOOL_CONVERSION = YES; 243 | CLANG_WARN_COMMA = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 246 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 247 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 248 | CLANG_WARN_EMPTY_BODY = YES; 249 | CLANG_WARN_ENUM_CONVERSION = YES; 250 | CLANG_WARN_INFINITE_RECURSION = YES; 251 | CLANG_WARN_INT_CONVERSION = YES; 252 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 253 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 254 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 256 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 261 | CLANG_WARN_UNREACHABLE_CODE = YES; 262 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 263 | CODE_SIGN_IDENTITY = "iPhone Developer"; 264 | COPY_PHASE_STRIP = NO; 265 | CURRENT_PROJECT_VERSION = 1; 266 | DEBUG_INFORMATION_FORMAT = dwarf; 267 | ENABLE_STRICT_OBJC_MSGSEND = YES; 268 | ENABLE_TESTABILITY = YES; 269 | GCC_C_LANGUAGE_STANDARD = gnu11; 270 | GCC_DYNAMIC_NO_PIC = NO; 271 | GCC_NO_COMMON_BLOCKS = YES; 272 | GCC_OPTIMIZATION_LEVEL = 0; 273 | GCC_PREPROCESSOR_DEFINITIONS = ( 274 | "DEBUG=1", 275 | "$(inherited)", 276 | ); 277 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 278 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 279 | GCC_WARN_UNDECLARED_SELECTOR = YES; 280 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 281 | GCC_WARN_UNUSED_FUNCTION = YES; 282 | GCC_WARN_UNUSED_VARIABLE = YES; 283 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 284 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 285 | MTL_FAST_MATH = YES; 286 | ONLY_ACTIVE_ARCH = YES; 287 | SDKROOT = iphoneos; 288 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 289 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 290 | VERSIONING_SYSTEM = "apple-generic"; 291 | VERSION_INFO_PREFIX = ""; 292 | }; 293 | name = Debug; 294 | }; 295 | 5B891C082222EC47002F31C6 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | CLANG_ANALYZER_NONNULL = YES; 300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 302 | CLANG_CXX_LIBRARY = "libc++"; 303 | CLANG_ENABLE_MODULES = YES; 304 | CLANG_ENABLE_OBJC_ARC = YES; 305 | CLANG_ENABLE_OBJC_WEAK = YES; 306 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 307 | CLANG_WARN_BOOL_CONVERSION = YES; 308 | CLANG_WARN_COMMA = YES; 309 | CLANG_WARN_CONSTANT_CONVERSION = YES; 310 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 313 | CLANG_WARN_EMPTY_BODY = YES; 314 | CLANG_WARN_ENUM_CONVERSION = YES; 315 | CLANG_WARN_INFINITE_RECURSION = YES; 316 | CLANG_WARN_INT_CONVERSION = YES; 317 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 318 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 319 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 321 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 322 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 323 | CLANG_WARN_STRICT_PROTOTYPES = YES; 324 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 325 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 326 | CLANG_WARN_UNREACHABLE_CODE = YES; 327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 328 | CODE_SIGN_IDENTITY = "iPhone Developer"; 329 | COPY_PHASE_STRIP = NO; 330 | CURRENT_PROJECT_VERSION = 1; 331 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 332 | ENABLE_NS_ASSERTIONS = NO; 333 | ENABLE_STRICT_OBJC_MSGSEND = YES; 334 | GCC_C_LANGUAGE_STANDARD = gnu11; 335 | GCC_NO_COMMON_BLOCKS = YES; 336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 338 | GCC_WARN_UNDECLARED_SELECTOR = YES; 339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 340 | GCC_WARN_UNUSED_FUNCTION = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 343 | MTL_ENABLE_DEBUG_INFO = NO; 344 | MTL_FAST_MATH = YES; 345 | SDKROOT = iphoneos; 346 | SWIFT_COMPILATION_MODE = wholemodule; 347 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 348 | VALIDATE_PRODUCT = YES; 349 | VERSIONING_SYSTEM = "apple-generic"; 350 | VERSION_INFO_PREFIX = ""; 351 | }; 352 | name = Release; 353 | }; 354 | 5B891C0A2222EC47002F31C6 /* Debug */ = { 355 | isa = XCBuildConfiguration; 356 | buildSettings = { 357 | APPLICATION_EXTENSION_API_ONLY = YES; 358 | CLANG_ENABLE_MODULES = YES; 359 | CODE_SIGN_IDENTITY = ""; 360 | CODE_SIGN_STYLE = Manual; 361 | DEFINES_MODULE = YES; 362 | DEVELOPMENT_TEAM = ""; 363 | DYLIB_COMPATIBILITY_VERSION = 1; 364 | DYLIB_CURRENT_VERSION = 1; 365 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 366 | INFOPLIST_FILE = froop/Info.plist; 367 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 368 | LD_RUNPATH_SEARCH_PATHS = ( 369 | "$(inherited)", 370 | "@executable_path/Frameworks", 371 | "@loader_path/Frameworks", 372 | ); 373 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froop; 374 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 375 | PROVISIONING_PROFILE_SPECIFIER = ""; 376 | SKIP_INSTALL = YES; 377 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 378 | SWIFT_VERSION = 5.0; 379 | TARGETED_DEVICE_FAMILY = "1,2"; 380 | }; 381 | name = Debug; 382 | }; 383 | 5B891C0B2222EC47002F31C6 /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | APPLICATION_EXTENSION_API_ONLY = YES; 387 | CLANG_ENABLE_MODULES = YES; 388 | CODE_SIGN_IDENTITY = ""; 389 | CODE_SIGN_STYLE = Manual; 390 | DEFINES_MODULE = YES; 391 | DEVELOPMENT_TEAM = ""; 392 | DYLIB_COMPATIBILITY_VERSION = 1; 393 | DYLIB_CURRENT_VERSION = 1; 394 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 395 | INFOPLIST_FILE = froop/Info.plist; 396 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 397 | LD_RUNPATH_SEARCH_PATHS = ( 398 | "$(inherited)", 399 | "@executable_path/Frameworks", 400 | "@loader_path/Frameworks", 401 | ); 402 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froop; 403 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 404 | PROVISIONING_PROFILE_SPECIFIER = ""; 405 | SKIP_INSTALL = YES; 406 | SWIFT_VERSION = 5.0; 407 | TARGETED_DEVICE_FAMILY = "1,2"; 408 | }; 409 | name = Release; 410 | }; 411 | 5B891C0D2222EC47002F31C6 /* Debug */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 415 | CODE_SIGN_STYLE = Automatic; 416 | DEVELOPMENT_TEAM = 62TZ9933HE; 417 | INFOPLIST_FILE = froopTests/Info.plist; 418 | LD_RUNPATH_SEARCH_PATHS = ( 419 | "$(inherited)", 420 | "@executable_path/Frameworks", 421 | "@loader_path/Frameworks", 422 | ); 423 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froopTests; 424 | PRODUCT_NAME = "$(TARGET_NAME)"; 425 | SWIFT_VERSION = 5.0; 426 | TARGETED_DEVICE_FAMILY = "1,2"; 427 | }; 428 | name = Debug; 429 | }; 430 | 5B891C0E2222EC47002F31C6 /* Release */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 434 | CODE_SIGN_STYLE = Automatic; 435 | DEVELOPMENT_TEAM = 62TZ9933HE; 436 | INFOPLIST_FILE = froopTests/Info.plist; 437 | LD_RUNPATH_SEARCH_PATHS = ( 438 | "$(inherited)", 439 | "@executable_path/Frameworks", 440 | "@loader_path/Frameworks", 441 | ); 442 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froopTests; 443 | PRODUCT_NAME = "$(TARGET_NAME)"; 444 | SWIFT_VERSION = 5.0; 445 | TARGETED_DEVICE_FAMILY = "1,2"; 446 | }; 447 | name = Release; 448 | }; 449 | /* End XCBuildConfiguration section */ 450 | 451 | /* Begin XCConfigurationList section */ 452 | 5B891BEF2222EC46002F31C6 /* Build configuration list for PBXProject "froop" */ = { 453 | isa = XCConfigurationList; 454 | buildConfigurations = ( 455 | 5B891C072222EC47002F31C6 /* Debug */, 456 | 5B891C082222EC47002F31C6 /* Release */, 457 | ); 458 | defaultConfigurationIsVisible = 0; 459 | defaultConfigurationName = Release; 460 | }; 461 | 5B891C092222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froop" */ = { 462 | isa = XCConfigurationList; 463 | buildConfigurations = ( 464 | 5B891C0A2222EC47002F31C6 /* Debug */, 465 | 5B891C0B2222EC47002F31C6 /* Release */, 466 | ); 467 | defaultConfigurationIsVisible = 0; 468 | defaultConfigurationName = Release; 469 | }; 470 | 5B891C0C2222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froopTests" */ = { 471 | isa = XCConfigurationList; 472 | buildConfigurations = ( 473 | 5B891C0D2222EC47002F31C6 /* Debug */, 474 | 5B891C0E2222EC47002F31C6 /* Release */, 475 | ); 476 | defaultConfigurationIsVisible = 0; 477 | defaultConfigurationName = Release; 478 | }; 479 | /* End XCConfigurationList section */ 480 | }; 481 | rootObject = 5B891BEC2222EC46002F31C6 /* Project object */; 482 | } 483 | -------------------------------------------------------------------------------- /froop.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /froop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /froop.xcodeproj/xcshareddata/xcbaselines/5B891BFD2222EC47002F31C6.xcbaseline/C6951AF0-5BDC-4962-A4A0-BEC937992614.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | froopTests 8 | 9 | testPerformanceMap() 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 2.08e-05 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /froop.xcodeproj/xcshareddata/xcbaselines/5B891BFD2222EC47002F31C6.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | C6951AF0-5BDC-4962-A4A0-BEC937992614 8 | 9 | localComputer 10 | 11 | busSpeedInMHz 12 | 100 13 | cpuCount 14 | 1 15 | cpuKind 16 | Intel Core i7 17 | cpuSpeedInMHz 18 | 3300 19 | logicalCPUCoresPerPackage 20 | 4 21 | modelCode 22 | MacBookPro13,2 23 | physicalCPUCoresPerPackage 24 | 2 25 | platformIdentifier 26 | com.apple.platform.macosx 27 | 28 | targetArchitecture 29 | x86_64 30 | targetDevice 31 | 32 | modelCode 33 | iPhone11,8 34 | platformIdentifier 35 | com.apple.platform.iphonesimulator 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /froop.xcodeproj/xcshareddata/xcschemes/froop.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /froop/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /froop/Threadly.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Threadly.swift 3 | // Threadly 4 | // 5 | // The MIT License (MIT) 6 | // 7 | // Copyright (c) 2017 Nikolai Vazquez 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | // 27 | 28 | import Foundation 29 | 30 | private final class _Key { 31 | var raw: pthread_key_t 32 | 33 | var box: Box? { 34 | guard let pointer = pthread_getspecific(raw) else { 35 | return nil 36 | } 37 | return Unmanaged>.fromOpaque(pointer).takeUnretainedValue() 38 | } 39 | 40 | init() { 41 | raw = pthread_key_t() 42 | pthread_key_create(&raw) { 43 | // Cast required because argument is optional on some 44 | // platforms (Linux) but not on others (macOS) 45 | guard let rawPointer = ($0 as UnsafeMutableRawPointer?) else { 46 | return 47 | } 48 | Unmanaged.fromOpaque(rawPointer).release() 49 | } 50 | } 51 | 52 | deinit { 53 | pthread_key_delete(raw) 54 | } 55 | 56 | func box(create: () throws -> T) rethrows -> Box { 57 | if let box = self.box { 58 | return box 59 | } else { 60 | let box = try Box(create()) 61 | pthread_setspecific(raw, Unmanaged.passRetained(box).toOpaque()) 62 | return box 63 | } 64 | } 65 | } 66 | 67 | /// A reference to a heap-allocated value. 68 | final class Box { 69 | /// The boxed value. 70 | var value: Value 71 | 72 | /// Creates an instance that boxes `value`. 73 | init(_ value: Value) { 74 | self.value = value 75 | } 76 | } 77 | 78 | /// A type that takes an initializer to create and then store a value that's 79 | /// unique to the current thread. The initializer is called the first time 80 | /// the thread-local is accessed, either through `inner` or `withValue(_:)`. 81 | /// 82 | /// - note: If the initial value isn't known until retrieval, use `DeferredThreadLocal`. 83 | public struct ThreadLocal: Hashable { 84 | fileprivate var _def: DeferredThreadLocal 85 | 86 | private var _create: () -> Value 87 | 88 | /// The hash value. 89 | public func hash(into hasher: inout Hasher) { 90 | hasher.combine(_def.hashValue) 91 | } 92 | 93 | /// Returns the inner boxed value for the current thread. 94 | var inner: Box { 95 | return _def.inner(createdWith: _create) 96 | } 97 | 98 | /// Creates an instance that will use `value` captured in its current 99 | /// state for an initial value. 100 | /// 101 | /// Sometimes this is what you want such as in cases where `value` is 102 | /// the result of an expensive operation or a copy-on-write type like 103 | /// `Array` or `Dictionary`. 104 | init(capturing value: Value) { 105 | self.init { [value] in 106 | value 107 | } 108 | } 109 | 110 | /// Creates an instance that will use `value` for an initial value. 111 | init(value: @escaping @autoclosure () -> Value) { 112 | self.init(create: value) 113 | } 114 | 115 | /// Creates an instance that will use `create` to generate an initial value. 116 | public init(create: @escaping () -> Value) { 117 | _create = create 118 | _def = DeferredThreadLocal() 119 | } 120 | 121 | /// Creates an instance that uses the same storage as `deferred` but with 122 | /// `create` as an initializer. 123 | init(fromDeferred deferred: DeferredThreadLocal, create: @escaping () -> Value) { 124 | _create = create 125 | _def = deferred 126 | } 127 | 128 | /// Returns the result of the closure performed on the value of `self`. 129 | public func withValue(_ body: (inout Value) throws -> T) rethrows -> T { 130 | return try body(&inner.value) 131 | } 132 | } 133 | 134 | /// A type that stores a value unique to the current thread. An initial value 135 | /// isn't provided until the inner thread-local value is accessed. 136 | /// 137 | /// - note: If the initial value is known at the time of initialization of the 138 | /// enclosing type, consider using `ThreadLocal` instead. 139 | struct DeferredThreadLocal: Hashable { 140 | fileprivate var _key: _Key 141 | 142 | /// The hash value. 143 | public func hash(into hasher: inout Hasher) { 144 | hasher.combine(_key.raw.hashValue) 145 | } 146 | 147 | /// Returns the inner boxed value for the current thread if it's been 148 | /// created, or `nil` otherwise. 149 | var inner: Box? { 150 | return _key.box 151 | } 152 | 153 | /// Creates an instance. 154 | init() { 155 | _key = _Key() 156 | } 157 | 158 | /// Returns the inner boxed value for the current thread, 159 | /// created with `create` if not previously initialized. 160 | func inner(createdWith create: () throws -> Value) rethrows -> Box { 161 | return try _key.box(create: create) 162 | } 163 | 164 | /// Returns the result of the closure performed on the inner thread-local 165 | /// value of `self`, or `nil` if uninitialized. 166 | func withValue(_ body: (inout Value) throws -> T) rethrows -> T? { 167 | return try inner.map { try body(&$0.value) } 168 | } 169 | 170 | /// Returns the result of the closure performed on the inner thread-local 171 | /// value of `self`, created with `create` if not previously initialized. 172 | func withValue(createdWith create: () throws -> Value, _ body: (inout Value) throws -> T) rethrows -> T { 173 | return try body(&inner(createdWith: create).value) 174 | } 175 | } 176 | 177 | /// A type that has a static thread-local instance. 178 | protocol ThreadLocalRetrievable { 179 | /// The thread-local boxed instance of `Self`. 180 | static var threadLocal: Box { get } 181 | 182 | /// Returns the result of performing the closure on the thread-local instance of `Self`. 183 | static func withThreadLocal(_ body: (inout Self) throws -> T) rethrows -> T 184 | } 185 | 186 | extension ThreadLocalRetrievable { 187 | /// Returns the result of performing the closure on the thread-local instance of `Self`. 188 | static func withThreadLocal(_ body: (inout Self) throws -> T) rethrows -> T { 189 | return try body(&threadLocal.value) 190 | } 191 | } 192 | 193 | /// Returns a Boolean value that indicates whether the two arguments have equal values. 194 | public func == (lhs: ThreadLocal, rhs: ThreadLocal) -> Bool { 195 | return lhs._def == rhs._def 196 | } 197 | 198 | /// Returns a Boolean value that indicates whether the two arguments have equal values. 199 | func == (lhs: DeferredThreadLocal, rhs: DeferredThreadLocal) -> Bool { 200 | return lhs._key.raw == rhs._key.raw 201 | } 202 | -------------------------------------------------------------------------------- /froop/froop.h: -------------------------------------------------------------------------------- 1 | // 2 | // froop.h 3 | // froop 4 | // 5 | // Created by martin on 2019-02-24. 6 | // Copyright © 2019 Lookback Ltd. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for froop. 12 | FOUNDATION_EXPORT double froopVersionNumber; 13 | 14 | //! Project version string for froop. 15 | FOUNDATION_EXPORT const unsigned char froopVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /froopTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /gen-docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | jazzy --clean --author Lookback --author_url https://lookback.io --github_url https://github.com/lookback/froop-swift --module froop --output docs/ 6 | --------------------------------------------------------------------------------