Contents.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. /*:
  2. > # IMPORTANT: To use `ReactiveCocoa.playground`, please:
  3. 1. Retrieve the project dependencies using one of the following terminal commands from the ReactiveCocoa project root directory:
  4. - `script/bootstrap`
  5. **OR**, if you have [Carthage](https://github.com/Carthage/Carthage) installed
  6. - `carthage checkout`
  7. 1. Open `ReactiveCocoa.xcworkspace`
  8. 1. Build `Result-Mac` scheme
  9. 1. Build `ReactiveCocoa-Mac` scheme
  10. 1. Finally open the `ReactiveCocoa.playground`
  11. 1. Choose `View > Show Debug Area`
  12. */
  13. import Result
  14. import ReactiveCocoa
  15. import Foundation
  16. /*:
  17. ## SignalProducer
  18. A **signal producer**, represented by the [`SignalProducer`](https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/ReactiveCocoa/Swift/SignalProducer.swift) type, creates
  19. [signals](https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/ReactiveCocoa/Swift/Signal.swift) and performs side effects.
  20. They can be used to represent operations or tasks, like network
  21. requests, where each invocation of `start()` will create a new underlying
  22. operation, and allow the caller to observe the result(s). The
  23. `startWithSignal()` variant gives access to the produced signal, allowing it to
  24. be observed multiple times if desired.
  25. Because of the behavior of `start()`, each signal created from the same
  26. producer may see a different ordering or version of events, or the stream might
  27. even be completely different! Unlike a plain signal, no work is started (and
  28. thus no events are generated) until an observer is attached, and the work is
  29. restarted anew for each additional observer.
  30. Starting a signal producer returns a [disposable](#disposables) that can be used to
  31. interrupt/cancel the work associated with the produced signal.
  32. Just like signals, signal producers can also be manipulated via primitives
  33. like `map`, `filter`, etc.
  34. Every signal primitive can be “lifted” to operate upon signal producers instead,
  35. using the `lift` method.
  36. Furthermore, there are additional primitives that control _when_ and _how_ work
  37. is started—for example, `times`.
  38. */
  39. /*:
  40. ### `Subscription`
  41. A SignalProducer represents an operation that can be started on demand. Starting the operation returns a Signal on which the result(s) of the operation can be observed. This behavior is sometimes also called "cold".
  42. This means that a subscriber will never miss any values sent by the SignalProducer.
  43. */
  44. scopedExample("Subscription") {
  45. let producer = SignalProducer<Int, NoError> { observer, _ in
  46. print("New subscription, starting operation")
  47. observer.sendNext(1)
  48. observer.sendNext(2)
  49. }
  50. let subscriber1 = Observer<Int, NoError>(next: { print("Subscriber 1 received \($0)") })
  51. let subscriber2 = Observer<Int, NoError>(next: { print("Subscriber 2 received \($0)") })
  52. print("Subscriber 1 subscribes to producer")
  53. producer.start(subscriber1)
  54. print("Subscriber 2 subscribes to producer")
  55. // Notice, how the producer will start the work again
  56. producer.start(subscriber2)
  57. }
  58. /*:
  59. ### `empty`
  60. A producer for a Signal that will immediately complete without sending
  61. any values.
  62. */
  63. scopedExample("`empty`") {
  64. let emptyProducer = SignalProducer<Int, NoError>.empty
  65. let observer = Observer<Int, NoError>(
  66. failed: { _ in print("error not called") },
  67. completed: { print("completed called") },
  68. next: { _ in print("next not called") }
  69. )
  70. emptyProducer.start(observer)
  71. }
  72. /*:
  73. ### `never`
  74. A producer for a Signal that never sends any events to its observers.
  75. */
  76. scopedExample("`never`") {
  77. let neverProducer = SignalProducer<Int, NoError>.never
  78. let observer = Observer<Int, NoError>(
  79. failed: { _ in print("error not called") },
  80. completed: { print("completed not called") },
  81. next: { _ in print("next not called") }
  82. )
  83. neverProducer.start(observer)
  84. }
  85. /*:
  86. ### `buffer`
  87. Creates a queue for events that replays them when new signals are
  88. created from the returned producer.
  89. When values are put into the returned observer (observer), they will be
  90. added to an internal buffer. If the buffer is already at capacity,
  91. the earliest (oldest) value will be dropped to make room for the new
  92. value.
  93. Signals created from the returned producer will stay alive until a
  94. terminating event is added to the queue. If the queue does not contain
  95. such an event when the Signal is started, all values sent to the
  96. returned observer will be automatically forwarded to the Signal’s
  97. observers until a terminating event is received.
  98. After a terminating event has been added to the queue, the observer
  99. will not add any further events. This _does not_ count against the
  100. value capacity so no buffered values will be dropped on termination.
  101. */
  102. scopedExample("`buffer`") {
  103. let (producer, observer) = SignalProducer<Int, NoError>.buffer(1)
  104. observer.sendNext(1)
  105. observer.sendNext(2)
  106. observer.sendNext(3)
  107. var values: [Int] = []
  108. producer.start { event in
  109. switch event {
  110. case let .Next(value):
  111. values.append(value)
  112. default:
  113. break
  114. }
  115. }
  116. print(values)
  117. observer.sendNext(4)
  118. print(values)
  119. }
  120. /*:
  121. ### `startWithSignal`
  122. Creates a Signal from the producer, passes it into the given closure,
  123. then starts sending events on the Signal when the closure has returned.
  124. The closure will also receive a disposable which can be used to
  125. interrupt the work associated with the signal and immediately send an
  126. `Interrupted` event.
  127. */
  128. scopedExample("`startWithSignal`") {
  129. var started = false
  130. var value: Int?
  131. SignalProducer<Int, NoError>(value: 42)
  132. .on(next: {
  133. value = $0
  134. })
  135. .startWithSignal { signal, disposable in
  136. print(value)
  137. }
  138. print(value)
  139. }
  140. /*:
  141. ### `startWithNext`
  142. Creates a Signal from the producer, then adds exactly one observer to
  143. the Signal, which will invoke the given callback when `next` events are
  144. received.
  145. Returns a Disposable which can be used to interrupt the work associated
  146. with the Signal, and prevent any future callbacks from being invoked.
  147. */
  148. scopedExample("`startWithNext`") {
  149. SignalProducer<Int, NoError>(value: 42)
  150. .startWithNext { value in
  151. print(value)
  152. }
  153. }
  154. /*:
  155. ### `startWithCompleted`
  156. Creates a Signal from the producer, then adds exactly one observer to
  157. the Signal, which will invoke the given callback when a `completed` event is
  158. received.
  159. Returns a Disposable which can be used to interrupt the work associated
  160. with the Signal.
  161. */
  162. scopedExample("`startWithCompleted`") {
  163. SignalProducer<Int, NoError>(value: 42)
  164. .startWithCompleted {
  165. print("completed called")
  166. }
  167. }
  168. /*:
  169. ### `startWithFailed`
  170. Creates a Signal from the producer, then adds exactly one observer to
  171. the Signal, which will invoke the given callback when a `failed` event is
  172. received.
  173. Returns a Disposable which can be used to interrupt the work associated
  174. with the Signal.
  175. */
  176. scopedExample("`startWithFailed`") {
  177. SignalProducer<Int, NSError>(error: NSError(domain: "example", code: 42, userInfo: nil))
  178. .startWithFailed { error in
  179. print(error)
  180. }
  181. }
  182. /*:
  183. ### `startWithInterrupted`
  184. Creates a Signal from the producer, then adds exactly one observer to
  185. the Signal, which will invoke the given callback when an `interrupted` event
  186. is received.
  187. Returns a Disposable which can be used to interrupt the work associated
  188. with the Signal.
  189. */
  190. scopedExample("`startWithInterrupted`") {
  191. let disposable = SignalProducer<Int, NoError>.never
  192. .startWithInterrupted {
  193. print("interrupted called")
  194. }
  195. disposable.dispose()
  196. }
  197. /*:
  198. ### `lift`
  199. Lifts an unary Signal operator to operate upon SignalProducers instead.
  200. In other words, this will create a new SignalProducer which will apply
  201. the given Signal operator to _every_ created Signal, just as if the
  202. operator had been applied to each Signal yielded from start().
  203. */
  204. scopedExample("`lift`") {
  205. var counter = 0
  206. let transform: Signal<Int, NoError> -> Signal<Int, NoError> = { signal in
  207. counter = 42
  208. return signal
  209. }
  210. SignalProducer<Int, NoError>(value: 0)
  211. .lift(transform)
  212. .startWithNext { _ in
  213. print(counter)
  214. }
  215. }
  216. /*:
  217. ### `map`
  218. Maps each value in the producer to a new value.
  219. */
  220. scopedExample("`map`") {
  221. SignalProducer<Int, NoError>(value: 1)
  222. .map { $0 + 41 }
  223. .startWithNext { value in
  224. print(value)
  225. }
  226. }
  227. /*:
  228. ### `mapError`
  229. Maps errors in the producer to a new error.
  230. */
  231. scopedExample("`mapError`") {
  232. SignalProducer<Int, NSError>(error: NSError(domain: "mapError", code: 42, userInfo: nil))
  233. .mapError { Error.Example($0.description) }
  234. .startWithFailed { error in
  235. print(error)
  236. }
  237. }
  238. /*:
  239. ### `filter`
  240. Preserves only the values of the producer that pass the given predicate.
  241. */
  242. scopedExample("`filter`") {
  243. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  244. .filter { $0 > 3}
  245. .startWithNext { value in
  246. print(value)
  247. }
  248. }
  249. /*:
  250. ### `take`
  251. Returns a producer that will yield the first `count` values from the
  252. input producer.
  253. */
  254. scopedExample("`take`") {
  255. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  256. .take(2)
  257. .startWithNext { value in
  258. print(value)
  259. }
  260. }
  261. /*:
  262. ### `observeOn`
  263. Forwards all events onto the given scheduler, instead of whichever
  264. scheduler they originally arrived upon.
  265. */
  266. scopedExample("`observeOn`") {
  267. let baseProducer = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  268. let completion = { print("is main thread? \(NSThread.currentThread().isMainThread)") }
  269. if #available(OSX 10.10, *) {
  270. baseProducer
  271. .observeOn(QueueScheduler(qos: QOS_CLASS_DEFAULT, name: "test"))
  272. .startWithCompleted(completion)
  273. }
  274. baseProducer
  275. .startWithCompleted(completion)
  276. }
  277. /*:
  278. ### `collect()`
  279. Returns a producer that will yield an array of values until it completes.
  280. */
  281. scopedExample("`collect()`") {
  282. SignalProducer<Int, NoError> { observer, disposable in
  283. observer.sendNext(1)
  284. observer.sendNext(2)
  285. observer.sendNext(3)
  286. observer.sendNext(4)
  287. observer.sendCompleted()
  288. }
  289. .collect()
  290. .startWithNext { value in
  291. print(value)
  292. }
  293. }
  294. /*:
  295. ### `collect(count:)`
  296. Returns a producer that will yield an array of values until it reaches a certain count.
  297. */
  298. scopedExample("`collect(count:)`") {
  299. SignalProducer<Int, NoError> { observer, disposable in
  300. observer.sendNext(1)
  301. observer.sendNext(2)
  302. observer.sendNext(3)
  303. observer.sendNext(4)
  304. observer.sendCompleted()
  305. }
  306. .collect(count: 2)
  307. .startWithNext { value in
  308. print(value)
  309. }
  310. }
  311. /*:
  312. ### `collect(predicate:)` matching values inclusively
  313. Returns a producer that will yield an array of values based on a predicate
  314. which matches the values collected.
  315. When producer completes any remaining values will be sent, the last values
  316. array may not match `predicate`. Alternatively, if were not collected any
  317. values will sent an empty array of values.
  318. */
  319. scopedExample("`collect(predicate:)` matching values inclusively") {
  320. SignalProducer<Int, NoError> { observer, disposable in
  321. observer.sendNext(1)
  322. observer.sendNext(2)
  323. observer.sendNext(3)
  324. observer.sendNext(4)
  325. observer.sendCompleted()
  326. }
  327. .collect { values in values.reduce(0, combine: +) == 3 }
  328. .startWithNext { value in
  329. print(value)
  330. }
  331. }
  332. /*:
  333. ### `collect(predicate:)` matching values exclusively
  334. Returns a producer that will yield an array of values based on a predicate
  335. which matches the values collected and the next value.
  336. When producer completes any remaining values will be sent, the last values
  337. array may not match `predicate`. Alternatively, if were not collected any
  338. values will sent an empty array of values.
  339. */
  340. scopedExample("`collect(predicate:)` matching values exclusively") {
  341. SignalProducer<Int, NoError> { observer, disposable in
  342. observer.sendNext(1)
  343. observer.sendNext(2)
  344. observer.sendNext(3)
  345. observer.sendNext(4)
  346. observer.sendCompleted()
  347. }
  348. .collect { values, next in next == 3 }
  349. .startWithNext { value in
  350. print(value)
  351. }
  352. }
  353. /*:
  354. ### `combineLatestWith`
  355. Combines the latest value of the receiver with the latest value from
  356. the given producer.
  357. The returned producer will not send a value until both inputs have sent at
  358. least one value each. If either producer is interrupted, the returned producer
  359. will also be interrupted.
  360. */
  361. scopedExample("`combineLatestWith`") {
  362. let producer1 = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  363. let producer2 = SignalProducer<Int, NoError>(values: [ 1, 2 ])
  364. producer1
  365. .combineLatestWith(producer2)
  366. .startWithNext { value in
  367. print("\(value)")
  368. }
  369. }
  370. /*:
  371. ### `skip`
  372. Returns a producer that will skip the first `count` values, then forward
  373. everything afterward.
  374. */
  375. scopedExample("`skip`") {
  376. let producer1 = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  377. producer1
  378. .skip(2)
  379. .startWithNext { value in
  380. print(value)
  381. }
  382. }
  383. /*:
  384. ### `materialize`
  385. Treats all Events from the input producer as plain values, allowing them to be
  386. manipulated just like any other value.
  387. In other words, this brings Events “into the monad.”
  388. When a Completed or Failed event is received, the resulting producer will send
  389. the Event itself and then complete. When an Interrupted event is received,
  390. the resulting producer will send the Event itself and then interrupt.
  391. */
  392. scopedExample("`materialize`") {
  393. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  394. .materialize()
  395. .startWithNext { value in
  396. print(value)
  397. }
  398. }
  399. /*:
  400. ### `sampleOn`
  401. Forwards the latest value from `self` whenever `sampler` sends a Next
  402. event.
  403. If `sampler` fires before a value has been observed on `self`, nothing
  404. happens.
  405. Returns a producer that will send values from `self`, sampled (possibly
  406. multiple times) by `sampler`, then complete once both input producers have
  407. completed, or interrupt if either input producer is interrupted.
  408. */
  409. scopedExample("`sampleOn`") {
  410. let baseProducer = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  411. let sampledOnProducer = SignalProducer<Int, NoError>(values: [ 1, 2 ])
  412. .map { _ in () }
  413. baseProducer
  414. .sampleOn(sampledOnProducer)
  415. .startWithNext { value in
  416. print(value)
  417. }
  418. }
  419. /*:
  420. ### `combinePrevious`
  421. Forwards events from `self` with history: values of the returned producer
  422. are a tuple whose first member is the previous value and whose second member
  423. is the current value. `initial` is supplied as the first member when `self`
  424. sends its first value.
  425. */
  426. scopedExample("`combinePrevious`") {
  427. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  428. .combinePrevious(42)
  429. .startWithNext { value in
  430. print("\(value)")
  431. }
  432. }
  433. /*:
  434. ### `scan`
  435. Aggregates `self`'s values into a single combined value. When `self` emits
  436. its first value, `combine` is invoked with `initial` as the first argument and
  437. that emitted value as the second argument. The result is emitted from the
  438. producer returned from `scan`. That result is then passed to `combine` as the
  439. first argument when the next value is emitted, and so on.
  440. */
  441. scopedExample("`scan`") {
  442. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  443. .scan(0, +)
  444. .startWithNext { value in
  445. print(value)
  446. }
  447. }
  448. /*:
  449. ### `reduce`
  450. Like `scan`, but sends only the final value and then immediately completes.
  451. */
  452. scopedExample("`reduce`") {
  453. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  454. .reduce(0, +)
  455. .startWithNext { value in
  456. print(value)
  457. }
  458. }
  459. /*:
  460. ### `skipRepeats`
  461. Forwards only those values from `self` which do not pass `isRepeat` with
  462. respect to the previous value. The first value is always forwarded.
  463. */
  464. scopedExample("`skipRepeats`") {
  465. SignalProducer<Int, NoError>(values: [ 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4 ])
  466. .skipRepeats(==)
  467. .startWithNext { value in
  468. print(value)
  469. }
  470. }
  471. /*:
  472. ### `skipWhile`
  473. Does not forward any values from `self` until `predicate` returns false,
  474. at which point the returned signal behaves exactly like `self`.
  475. */
  476. scopedExample("`skipWhile`") {
  477. SignalProducer<Int, NoError>(values: [ 3, 3, 3, 3, 1, 2, 3, 4 ])
  478. .skipWhile { $0 > 2 }
  479. .startWithNext { value in
  480. print(value)
  481. }
  482. }
  483. /*:
  484. ### `takeUntilReplacement`
  485. Forwards events from `self` until `replacement` begins sending events.
  486. Returns a producer which passes through `Next`, `Failed`, and `Interrupted`
  487. events from `self` until `replacement` sends an event, at which point the
  488. returned producer will send that event and switch to passing through events
  489. from `replacement` instead, regardless of whether `self` has sent events
  490. already.
  491. */
  492. scopedExample("`takeUntilReplacement`") {
  493. let (replacementSignal, incomingReplacementObserver) = Signal<Int, NoError>.pipe()
  494. let baseProducer = SignalProducer<Int, NoError> { incomingObserver, _ in
  495. incomingObserver.sendNext(1)
  496. incomingObserver.sendNext(2)
  497. incomingObserver.sendNext(3)
  498. incomingReplacementObserver.sendNext(42)
  499. incomingObserver.sendNext(4)
  500. incomingReplacementObserver.sendNext(42)
  501. }
  502. let producer = baseProducer.takeUntilReplacement(replacementSignal)
  503. producer.startWithNext { value in
  504. print(value)
  505. }
  506. }
  507. /*:
  508. ### `takeLast`
  509. Waits until `self` completes and then forwards the final `count` values
  510. on the returned producer.
  511. */
  512. scopedExample("`takeLast`") {
  513. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  514. .takeLast(2)
  515. .startWithNext { value in
  516. print(value)
  517. }
  518. }
  519. /*:
  520. ### `ignoreNil`
  521. Unwraps non-`nil` values and forwards them on the returned signal, `nil`
  522. values are dropped.
  523. */
  524. scopedExample("`ignoreNil`") {
  525. SignalProducer<Int?, NoError>(values: [ nil, 1, 2, nil, 3, 4, nil ])
  526. .ignoreNil()
  527. .startWithNext { value in
  528. print(value)
  529. }
  530. }
  531. /*:
  532. ### `zipWith`
  533. Zips elements of two producers into pairs. The elements of any Nth pair
  534. are the Nth elements of the two input producers.
  535. */
  536. scopedExample("`zipWith`") {
  537. let baseProducer = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  538. let zippedProducer = SignalProducer<Int, NoError>(values: [ 42, 43 ])
  539. baseProducer
  540. .zipWith(zippedProducer)
  541. .startWithNext { value in
  542. print("\(value)")
  543. }
  544. }
  545. /*:
  546. ### `times`
  547. Repeats `self` a total of `count` times. Repeating `1` times results in
  548. an equivalent signal producer.
  549. */
  550. scopedExample("`times`") {
  551. var counter = 0
  552. SignalProducer<(), NoError> { observer, disposable in
  553. counter += 1
  554. observer.sendCompleted()
  555. }
  556. .times(42)
  557. .start()
  558. print(counter)
  559. }
  560. /*:
  561. ### `retry`
  562. Ignores failures up to `count` times.
  563. */
  564. scopedExample("`retry`") {
  565. var tries = 0
  566. SignalProducer<Int, NSError> { observer, disposable in
  567. if tries == 0 {
  568. tries += 1
  569. observer.sendFailed(NSError(domain: "retry", code: 0, userInfo: nil))
  570. } else {
  571. observer.sendNext(42)
  572. observer.sendCompleted()
  573. }
  574. }
  575. .retry(1)
  576. .startWithResult { result in
  577. print(result)
  578. }
  579. }
  580. /*:
  581. ### `then`
  582. Waits for completion of `producer`, *then* forwards all events from
  583. `replacement`. Any failure sent from `producer` is forwarded immediately, in
  584. which case `replacement` will not be started, and none of its events will be
  585. be forwarded. All values sent from `producer` are ignored.
  586. */
  587. scopedExample("`then`") {
  588. let baseProducer = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  589. let thenProducer = SignalProducer<Int, NoError>(value: 42)
  590. baseProducer
  591. .then(thenProducer)
  592. .startWithNext { value in
  593. print(value)
  594. }
  595. }
  596. /*:
  597. ### `replayLazily`
  598. Creates a new `SignalProducer` that will multicast values emitted by
  599. the underlying producer, up to `capacity`.
  600. This means that all clients of this `SignalProducer` will see the same version
  601. of the emitted values/errors.
  602. The underlying `SignalProducer` will not be started until `self` is started
  603. for the first time. When subscribing to this producer, all previous values
  604. (up to `capacity`) will be emitted, followed by any new values.
  605. If you find yourself needing *the current value* (the last buffered value)
  606. you should consider using `PropertyType` instead, which, unlike this operator,
  607. will guarantee at compile time that there's always a buffered value.
  608. This operator is not recommended in most cases, as it will introduce an implicit
  609. relationship between the original client and the rest, so consider alternatives
  610. like `PropertyType`, `SignalProducer.buffer`, or representing your stream using
  611. a `Signal` instead.
  612. This operator is only recommended when you absolutely need to introduce
  613. a layer of caching in front of another `SignalProducer`.
  614. This operator has the same semantics as `SignalProducer.buffer`.
  615. */
  616. scopedExample("`replayLazily`") {
  617. let baseProducer = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4, 42 ])
  618. .replayLazily(2)
  619. baseProducer.startWithNext { value in
  620. print(value)
  621. }
  622. baseProducer.startWithNext { value in
  623. print(value)
  624. }
  625. baseProducer.startWithNext { value in
  626. print(value)
  627. }
  628. }
  629. /*:
  630. ### `flatMap(.Latest)`
  631. Maps each event from `self` to a new producer, then flattens the
  632. resulting producers (into a producer of values), according to the
  633. semantics of the given strategy.
  634. If `self` or any of the created producers fail, the returned producer
  635. will forward that failure immediately.
  636. */
  637. scopedExample("`flatMap(.Latest)`") {
  638. SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  639. .flatMap(.Latest) { SignalProducer(value: $0 + 3) }
  640. .startWithNext { value in
  641. print(value)
  642. }
  643. }
  644. /*:
  645. ### `flatMapError`
  646. Catches any failure that may occur on the input producer, mapping to a new producer
  647. that starts in its place.
  648. */
  649. scopedExample("`flatMapError`") {
  650. SignalProducer<Int, NSError>(error: NSError(domain: "flatMapError", code: 42, userInfo: nil))
  651. .flatMapError { SignalProducer<Int, NoError>(value: $0.code) }
  652. .startWithNext { value in
  653. print(value)
  654. }
  655. }
  656. /*:
  657. ### `sampleWith`
  658. Forwards the latest value from `self` with the value from `sampler` as a tuple,
  659. only when `sampler` sends a Next event.
  660. If `sampler` fires before a value has been observed on `self`, nothing happens.
  661. Returns a producer that will send values from `self` and `sampler`,
  662. sampled (possibly multiple times) by `sampler`, then complete once both
  663. input producers have completed, or interrupt if either input producer is interrupted.
  664. */
  665. scopedExample("`sampleWith`") {
  666. let producer = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4 ])
  667. let sampler = SignalProducer<String, NoError>(values: [ "a", "b" ])
  668. let result = producer.sampleWith(sampler)
  669. result.startWithNext { left, right in
  670. print("\(left) \(right)")
  671. }
  672. }
  673. /*:
  674. ### `logEvents`
  675. Logs all events that the receiver sends.
  676. By default, it will print to the standard output.
  677. */
  678. scopedExample("`log events`") {
  679. let baseProducer = SignalProducer<Int, NoError>(values: [ 1, 2, 3, 4, 42 ])
  680. baseProducer
  681. .logEvents(identifier: "Playground is fun!")
  682. .start()
  683. }