RACSignal.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. //
  2. // RACSignal.h
  3. // ReactiveCocoa
  4. //
  5. // Created by Josh Abernathy on 3/1/12.
  6. // Copyright (c) 2012 GitHub, Inc. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #import "RACStream.h"
  10. @class RACDisposable;
  11. @class RACScheduler;
  12. @class RACSubject;
  13. @protocol RACSubscriber;
  14. @interface RACSignal : RACStream
  15. /// Creates a new signal. This is the preferred way to create a new signal
  16. /// operation or behavior.
  17. ///
  18. /// Events can be sent to new subscribers immediately in the `didSubscribe`
  19. /// block, but the subscriber will not be able to dispose of the signal until
  20. /// a RACDisposable is returned from `didSubscribe`. In the case of infinite
  21. /// signals, this won't _ever_ happen if events are sent immediately.
  22. ///
  23. /// To ensure that the signal is disposable, events can be scheduled on the
  24. /// +[RACScheduler currentScheduler] (so that they're deferred, not sent
  25. /// immediately), or they can be sent in the background. The RACDisposable
  26. /// returned by the `didSubscribe` block should cancel any such scheduling or
  27. /// asynchronous work.
  28. ///
  29. /// didSubscribe - Called when the signal is subscribed to. The new subscriber is
  30. /// passed in. You can then manually control the <RACSubscriber> by
  31. /// sending it -sendNext:, -sendError:, and -sendCompleted,
  32. /// as defined by the operation you're implementing. This block
  33. /// should return a RACDisposable which cancels any ongoing work
  34. /// triggered by the subscription, and cleans up any resources or
  35. /// disposables created as part of it. When the disposable is
  36. /// disposed of, the signal must not send any more events to the
  37. /// `subscriber`. If no cleanup is necessary, return nil.
  38. ///
  39. /// **Note:** The `didSubscribe` block is called every time a new subscriber
  40. /// subscribes. Any side effects within the block will thus execute once for each
  41. /// subscription, not necessarily on one thread, and possibly even
  42. /// simultaneously!
  43. + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe;
  44. /// Returns a signal that immediately sends the given error.
  45. + (RACSignal *)error:(NSError *)error;
  46. /// Returns a signal that never completes.
  47. + (RACSignal *)never;
  48. /// Immediately schedules the given block on the given scheduler. The block is
  49. /// given a subscriber to which it can send events.
  50. ///
  51. /// scheduler - The scheduler on which `block` will be scheduled and results
  52. /// delivered. Cannot be nil.
  53. /// block - The block to invoke. Cannot be NULL.
  54. ///
  55. /// Returns a signal which will send all events sent on the subscriber given to
  56. /// `block`. All events will be sent on `scheduler` and it will replay any missed
  57. /// events to new subscribers.
  58. + (RACSignal *)startEagerlyWithScheduler:(RACScheduler *)scheduler block:(void (^)(id<RACSubscriber> subscriber))block;
  59. /// Invokes the given block only on the first subscription. The block is given a
  60. /// subscriber to which it can send events.
  61. ///
  62. /// Note that disposing of the subscription to the returned signal will *not*
  63. /// dispose of the underlying subscription. If you need that behavior, see
  64. /// -[RACMulticastConnection autoconnect]. The underlying subscription will never
  65. /// be disposed of. Because of this, `block` should never return an infinite
  66. /// signal since there would be no way of ending it.
  67. ///
  68. /// scheduler - The scheduler on which the block should be scheduled. Note that
  69. /// if given +[RACScheduler immediateScheduler], the block will be
  70. /// invoked synchronously on the first subscription. Cannot be nil.
  71. /// block - The block to invoke on the first subscription. Cannot be NULL.
  72. ///
  73. /// Returns a signal which will pass through the events sent to the subscriber
  74. /// given to `block` and replay any missed events to new subscribers.
  75. + (RACSignal *)startLazilyWithScheduler:(RACScheduler *)scheduler block:(void (^)(id<RACSubscriber> subscriber))block;
  76. @end
  77. @interface RACSignal (RACStream)
  78. /// Returns a signal that immediately sends the given value and then completes.
  79. + (RACSignal *)return:(id)value;
  80. /// Returns a signal that immediately completes.
  81. + (RACSignal *)empty;
  82. /// Subscribes to `signal` when the source signal completes.
  83. - (RACSignal *)concat:(RACSignal *)signal;
  84. /// Zips the values in the receiver with those of the given signal to create
  85. /// RACTuples.
  86. ///
  87. /// The first `next` of each stream will be combined, then the second `next`, and
  88. /// so forth, until either signal completes or errors.
  89. ///
  90. /// signal - The signal to zip with. This must not be `nil`.
  91. ///
  92. /// Returns a new signal of RACTuples, representing the combined values of the
  93. /// two signals. Any error from one of the original signals will be forwarded on
  94. /// the returned signal.
  95. - (RACSignal *)zipWith:(RACSignal *)signal;
  96. @end
  97. @interface RACSignal (Subscription)
  98. /// Subscribes `subscriber` to changes on the receiver. The receiver defines which
  99. /// events it actually sends and in what situations the events are sent.
  100. ///
  101. /// Subscription will always happen on a valid RACScheduler. If the
  102. /// +[RACScheduler currentScheduler] cannot be determined at the time of
  103. /// subscription (e.g., because the calling code is running on a GCD queue or
  104. /// NSOperationQueue), subscription will occur on a private background scheduler.
  105. /// On the main thread, subscriptions will always occur immediately, with a
  106. /// +[RACScheduler currentScheduler] of +[RACScheduler mainThreadScheduler].
  107. ///
  108. /// This method must be overridden by any subclasses.
  109. ///
  110. /// Returns nil or a disposable. You can call -[RACDisposable dispose] if you
  111. /// need to end your subscription before it would "naturally" end, either by
  112. /// completing or erroring. Once the disposable has been disposed, the subscriber
  113. /// won't receive any more events from the subscription.
  114. - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber;
  115. /// Convenience method to subscribe to the `next` event.
  116. ///
  117. /// This corresponds to `IObserver<T>.OnNext` in Rx.
  118. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;
  119. /// Convenience method to subscribe to the `next` and `completed` events.
  120. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock completed:(void (^)(void))completedBlock;
  121. /// Convenience method to subscribe to the `next`, `completed`, and `error` events.
  122. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock;
  123. /// Convenience method to subscribe to `error` events.
  124. ///
  125. /// This corresponds to the `IObserver<T>.OnError` in Rx.
  126. - (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock;
  127. /// Convenience method to subscribe to `completed` events.
  128. ///
  129. /// This corresponds to the `IObserver<T>.OnCompleted` in Rx.
  130. - (RACDisposable *)subscribeCompleted:(void (^)(void))completedBlock;
  131. /// Convenience method to subscribe to `next` and `error` events.
  132. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock;
  133. /// Convenience method to subscribe to `error` and `completed` events.
  134. - (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock;
  135. @end
  136. /// Additional methods to assist with debugging.
  137. @interface RACSignal (Debugging)
  138. /// Logs all events that the receiver sends.
  139. - (RACSignal *)logAll;
  140. /// Logs each `next` that the receiver sends.
  141. - (RACSignal *)logNext;
  142. /// Logs any error that the receiver sends.
  143. - (RACSignal *)logError;
  144. /// Logs any `completed` event that the receiver sends.
  145. - (RACSignal *)logCompleted;
  146. @end
  147. /// Additional methods to assist with unit testing.
  148. ///
  149. /// **These methods should never ship in production code.**
  150. @interface RACSignal (Testing)
  151. /// Spins the main run loop for a short while, waiting for the receiver to send a `next`.
  152. ///
  153. /// **Because this method executes the run loop recursively, it should only be used
  154. /// on the main thread, and only from a unit test.**
  155. ///
  156. /// defaultValue - Returned if the receiver completes or errors before sending
  157. /// a `next`, or if the method times out. This argument may be
  158. /// nil.
  159. /// success - If not NULL, set to whether the receiver completed
  160. /// successfully.
  161. /// error - If not NULL, set to any error that occurred.
  162. ///
  163. /// Returns the first value received, or `defaultValue` if no value is received
  164. /// before the signal finishes or the method times out.
  165. - (id)asynchronousFirstOrDefault:(id)defaultValue success:(BOOL *)success error:(NSError **)error;
  166. /// Spins the main run loop for a short while, waiting for the receiver to complete.
  167. ///
  168. /// **Because this method executes the run loop recursively, it should only be used
  169. /// on the main thread, and only from a unit test.**
  170. ///
  171. /// error - If not NULL, set to any error that occurs.
  172. ///
  173. /// Returns whether the signal completed successfully before timing out. If NO,
  174. /// `error` will be set to any error that occurred.
  175. - (BOOL)asynchronouslyWaitUntilCompleted:(NSError **)error;
  176. @end
  177. @interface RACSignal (Deprecated)
  178. + (RACSignal *)start:(id (^)(BOOL *success, NSError **error))block __attribute__((deprecated("Use +startEagerlyWithScheduler:block: instead")));
  179. + (RACSignal *)startWithScheduler:(RACScheduler *)scheduler subjectBlock:(void (^)(RACSubject *subject))block __attribute__((deprecated("Use +startEagerlyWithScheduler:block: instead")));
  180. + (RACSignal *)startWithScheduler:(RACScheduler *)scheduler block:(id (^)(BOOL *success, NSError **error))block __attribute__((deprecated("Use +startEagerlyWithScheduler:block: instead")));
  181. @end