A signal, represented by the RACSignal class, is a push-driven stream. Signals generally represent data that will be delivered in the future. As work is performed or data is received, values are sent on the signal, which pushes them out to any subscribers. Users must subscribe to a signal in order to access its values.
信号是一种 “推送” 类型的流。
信号代表着将来要传输的数据,值通过信号传递给订阅者;
用户须订阅信号才能接收到这些值。
2.冷热信号
信号分为冷信号和热信号两种:
冷信号是被动的,被订阅之后才能发送消息;
热信号是主动的,即使未被订阅也能不断推送新消息;
冷信号只能1-1,对应一个订阅者,当有新订阅者时消息会重新发送一遍;
热信号可以1-N,可以有多个订阅者,信号可与多个订阅者共享信息;
#2.1.冷信号
RACDynamicSignal
RACEmptySignal
RACErrorSignal
RACReturnSignal
RACChannelTerminal
#2.2.热信号
RACSubject
RACBehaviorSubject
RACGroupedSignal
RACReplaySubject
二.订阅者
关于RACSubscriber的描述:
A subscriber is anything that is waiting or capable of waiting for events from a signal. Within RAC, a subscriber is represented as any object that conforms to the RACSubscriber protocol.
Subscriptions retain their signals, and are automatically disposed of when the signal completes or errors. Subscriptions can also be disposed of manually.
订阅者表示正在等待信号发送事件的对象。
当信号有新数据时,通过这个订阅者发送新值。
订阅者在信号发送完成或者错误事件时会自动销毁。
这些关于信号与订阅者的描述很容易让人联想到APNs,两者机制很相似:
iOS设备提前注册推送服务(订阅);
苹果的推送服务器推送消息(事件);
iOS设备接收到消息并处理自己的业务(响应)。
iOS设备就是订阅者,苹果的 APNs 服务作为一个整体而被视为信号流。二者是 N 对 1 的关系。
/// 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<ValueType> *)createSignal:(RACDisposable * _Nullable (^)(id<RACSubscriber> subscriber))didSubscribe RAC_WARN_UNUSED_RESULT;
// These callbacks should only be accessed while synchronized on self. @property (nonatomic, copy) void (^next)(id value); @property (nonatomic, copy) void (^error)(NSError *error); @property (nonatomic, copy) void (^completed)(void);
/// Sends the next value to subscribers. /// /// value - The value to send. This can be `nil`. - (void)sendNext:(nullableid)value;
/// Sends the error to subscribers. /// /// error - The error to send. This can be `nil`. /// /// This terminates the subscription, and invalidates the subscriber (such that /// it cannot subscribe to anything else in the future). - (void)sendError:(nullableNSError *)error;
/// Sends completed to subscribers. /// /// This terminates the subscription, and invalidates the subscriber (such that /// it cannot subscribe to anything else in the future). - (void)sendCompleted;
/// Sends the next value to subscribers. /// /// value - The value to send. This can be `nil`. - (void)sendNext:(nullable id)value;
/// Sends the error to subscribers. /// /// error - The error to send. This can be `nil`. /// /// This terminates the subscription, and invalidates the subscriber (such that /// it cannot subscribe to anything else in the future). - (void)sendError:(nullable NSError *)error;
/// Sends completed to subscribers. /// /// This terminates the subscription, and invalidates the subscriber (such that /// it cannot subscribe to anything else in the future). - (void)sendCompleted;
/// Sends the subscriber a disposable that represents one of its subscriptions. /// /// A subscriber may receive multiple disposables if it gets subscribed to /// multiple signals; however, any error or completed events must terminate _all_ /// subscriptions. - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;
以上几个方法主要用来向订阅者发送数据或更新状态。
热信号正是实现了此协议,才能在没有订阅者的情况下也能主动发送数据。以RACSubject为例:
1 2 3 4 5 6
/// A subject can be thought of as a signal that you can manually control by /// sending next, completed, and error. /// /// They're most helpful in bridging the non-RAC world to RAC, since they let you /// manually control the sending of events. @interfaceRACSubject<ValueType> : RACSignal<ValueType> <RACSubscriber>
Signals are cold by default, meaning that they start doing work each time a new subscription is added. This behavior is usually desirable, because it means that data will be freshly recalculated for each subscriber, but it can be problematic if the signal has side effects or the work is expensive (for example, sending a network request).
A multicast connection encapsulates the idea of sharing one subscription to a signal to many subscribers. This is most often needed if the subscription to the underlying signal involves side-effects or shouldn’t be called more than once.