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