RACStream
RACStream
是 RACSignal
的父类。它是一个抽象类,定义了一个传输变量的“流结构”,并且声明了一些作为 Stream 结构所支持的一些方法,其中在主 @interface
下声明的方法是必须要由子类去实现的。
+ (__kindof RACStream<ValueType> *)empty;
+ (__kindof RACStream<ValueType> *)return:(nullable ValueType)value;
- (__kindof RACStream *)bind:(RACStreamBindBlock (^)(void))block;
- (__kindof RACStream *)concat:(RACStream *)stream;
- (__kindof RACStream *)zipWith:(RACStream *)stream;
+empty
方法
// RACSignal.m
+ (RACSignal *)empty {
return [RACEmptySignal empty];
}
// RACEmptySignal.m
+ (RACSignal *)empty {
#ifdef DEBUG
// Create multiple instances of this class in DEBUG so users can set custom
// names on each.
return [[[self alloc] init] setNameWithFormat:@"+empty"];
#else
static id singleton;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
singleton = [[self alloc] init];
});
return singleton;
#endif
}
实现很简短,直接返回了一个 RACEmptySignal
,它是一个空的 Signal ,在被订阅时立即且同步地向所有 Subscriber 发送 Completed 事件。可以猜到,它的 -subscribe:
方法干的唯一一件事应该就是“安排”(schedule),安排一个 Completed 👇
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
return [RACScheduler.subscriptionScheduler schedule:^{
[subscriber sendCompleted];
}];
}
-return:
方法
// RACSignal.m
+ (RACSignal *)return:(id)value {
return [RACReturnSignal return:value];
}
// RACReturnSignal.m
+ (RACSignal *)return:(id)value {
#ifndef DEBUG
if (value == RACUnit.defaultUnit) {
static RACReturnSignal *unitSingleton;
static dispatch_once_t unitPred;
dispatch_once(&unitPred, ^{
unitSingleton = [[self alloc] init];
unitSingleton->_value = RACUnit.defaultUnit;
});
return unitSingleton;
} else if (value == nil) {
static RACReturnSignal *nilSingleton;
static dispatch_once_t nilPred;
dispatch_once(&nilPred, ^{
nilSingleton = [[self alloc] init];
nilSingleton->_value = nil;
});
return nilSingleton;
}
#endif
RACReturnSignal *signal = [[self alloc] init];
signal->_value = value;
#ifdef DEBUG
[signal setNameWithFormat:@"+return: %@", value];
#endif
return signal;
}
除去 debug 代码,实现也是很简短,直接返回一个 RACReturnSignal
的实例,value
等于传入的值。它是一个只包含一个 value
的 Signal ,在被订阅时立即且同步地向所有 Subscriber 发送包含这个 value
的 Next 事件,然后 Complete 。所以它的 -subscribe:
方法是这样的👇
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
return [RACScheduler.subscriptionScheduler schedule:^{
[subscriber sendNext:self.value];
[subscriber sendCompleted];
}];
}
-bind:
方法
- (RACSignal *)bind:(RACSignalBindBlock (^)(void))block {
NSCParameterAssert(block != NULL);
/*
* -bind: should:
*
* 1. Subscribe to the original signal of values.
* 2. Any time the original signal sends a value, transform it using the binding block.
* 3. If the binding block returns a signal, subscribe to it, and pass all of its values through to the subscriber as they're received.
* 4. If the binding block asks the bind to terminate, complete the _original_ signal.
* 5. When _all_ signals complete, send completed to the subscriber.
*
* If any signal sends an error at any point, send that to the subscriber.
*/
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
RACSignalBindBlock bindingBlock = block();
__block volatile int32_t signalCount = 1; // indicates self
RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable];
// 为突出重点,暂时省略
void (^completeSignal)(RACDisposable *) = ^(RACDisposable *finishedDisposable) { ... };
// 为突出重点,暂时省略
void (^addSignal)(RACSignal *) = ^(RACSignal *signal) { ... };
@autoreleasepool {
RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init];
[compoundDisposable addDisposable:selfDisposable];
RACDisposable *bindingDisposable = [self subscribeNext:^(id x) {
// Manually check disposal to handle synchronous errors.
if (compoundDisposable.disposed) return;
BOOL stop = NO;
id signal = bindingBlock(x, &stop);
@autoreleasepool {
if (signal != nil) addSignal(signal);
if (signal == nil || stop) {
[selfDisposable dispose];
completeSignal(selfDisposable);
}
}
} error:^(NSError *error) {
[compoundDisposable dispose];
[subscriber sendError:error];
} completed:^{
@autoreleasepool {
completeSignal(selfDisposable);
}
}];
selfDisposable.disposable = bindingDisposable;
}
return compoundDisposable;
}] setNameWithFormat:@"[%@] -bind:", self.name];
}
可见 -bind:
方法首先订阅了 self
,我们称其为 Original Signal 。每当 Original Signal 收到事件时,都会调用外部传进来的 bindingBlock
,并把事件的 value x
作为 block 的参数,产生一个新的 Signal 。随后把这个 Signal 传给 addSignal
block👇
void (^addSignal)(RACSignal *) = ^(RACSignal *signal) {
OSAtomicIncrement32Barrier(&signalCount);
RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init];
[compoundDisposable addDisposable:selfDisposable];
RACDisposable *disposable = [signal subscribeNext:^(id x) {
[subscriber sendNext:x];
} error:^(NSError *error) {
[compoundDisposable dispose];
[subscriber sendError:error];
} completed:^{
@autoreleasepool {
completeSignal(selfDisposable);
}
}];
selfDisposable.disposable = disposable;
};
在这个 block 中,它订阅了传进来的 signal
,并且将产生的所有事件透传给 -bind:
方法返回的 Signal 的 Subscriber 。
如果 bindingBlock
返回的 Signal 是 nil
或者 bindingBlock
将 stop
的值修改为了 YES
,那就会把 selfDisposable
传给 completeBlock
👇
void (^completeSignal)(RACDisposable *) = ^(RACDisposable *finishedDisposable) {
if (OSAtomicDecrement32Barrier(&signalCount) == 0) {
[subscriber sendCompleted];
[compoundDisposable dispose];
} else {
[compoundDisposable removeDisposable:finishedDisposable];
}
};
在这个 block 中,判断了当前还没有 Complete 的 Signal 数量,如果为 0 的话,将会向 -bind:
方法返回的 Signal 的 Subscriber 发送 Complete 。
其实作者在源码注释中已经对 -bind:
方法做了一个简短的介绍,在此作为总结。
-bind: should:
- Subscribe to the original signal of values.
- Any time the original signal sends a value, transform it using the binding block.
- If the binding block returns a signal, subscribe to it, and pass all of its values through to the subscriber as they're received.
- If the binding block asks the bind to terminate, complete the original signal.
- When all signals complete, send completed to the subscriber.
If any signal sends an error at any point, send that to the subscriber.
-concat:
方法
这个方法实现了两个 Signal 的首尾拼接。

// Demo
RACSignal *signal0 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"signal0");
[subscriber sendNext:@"0"];
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"signal1");
[subscriber sendNext:@"A"];
[subscriber sendNext:@"B"];
[subscriber sendNext:@"C"];
[subscriber sendNext:@"D"];
[subscriber sendCompleted];
return nil;
}];
[[signal0 concat:signal1] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"concat: %@", x);
}];
// output:
// signal0
// concat: 0
// concat: 1
// concat: 2
// signal1
// concat: A
// concat: B
// concat: C
// concat: D
看一下源码实现👇
- (RACSignal *)concat:(RACSignal *)signal {
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
RACCompoundDisposable *compoundDisposable = [[RACCompoundDisposable alloc] init];
RACDisposable *sourceDisposable = [self subscribeNext:^(id x) {
[subscriber sendNext:x];
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
// subscribes to concatted signal when source signal completes
RACDisposable *concattedDisposable = [signal subscribe:subscriber];
[compoundDisposable addDisposable:concattedDisposable];
}];
[compoundDisposable addDisposable:sourceDisposable];
return compoundDisposable;
}] setNameWithFormat:@"[%@] -concat: %@", self.name, signal];
}
-concat:
方法的实现核心在于第 11 行,也就是在 Source Signal 发送 Complete 的时候,紧接着对 Concatted Signal 进行了订阅。
-zipWith:
方法
这个方法实现了两个 Signal 的绑定,用两个 Signal 发出的最新事件合并成一个 RACTuple
,并把这个 RACTuple
发给 Subscriber。当两个 Signal 中任何一个 Complete ,都会触发整个 Signal 的 Complete 。
RACTuple
是一个 RAC 库自身实现的元组结构。类似于 Swift 中的 Tuple ,它是一个可以包含不同类型元素的集合。

// Demo
RACSignal *signal0 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"signal0");
[subscriber sendNext:@"0"];
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"signal1");
[subscriber sendNext:@"A"];
[subscriber sendNext:@"B"];
[subscriber sendNext:@"C"];
[subscriber sendNext:@"D"];
[subscriber sendCompleted];
return nil;
}];
// output
// signal0
// signal1
// zip: (0, A)
// zip: (1, B)
// zip: (2, C)
看一下源码实现👇
- (RACSignal *)zipWith:(RACSignal *)signal {
NSCParameterAssert(signal != nil);
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
__block BOOL selfCompleted = NO;
NSMutableArray *selfValues = [NSMutableArray array];
__block BOOL otherCompleted = NO;
NSMutableArray *otherValues = [NSMutableArray array];
// 为突出重点,暂时省略
void (^sendCompletedIfNecessary)(void) = ^{ ... };
// 为突出重点,暂时省略
void (^sendNext)(void) = ^{ ... };
RACDisposable *selfDisposable = [self subscribeNext:^(id x) {
@synchronized (selfValues) {
[selfValues addObject:x ?: RACTupleNil.tupleNil];
sendNext();
}
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
@synchronized (selfValues) {
selfCompleted = YES;
sendCompletedIfNecessary();
}
}];
RACDisposable *otherDisposable = [signal subscribeNext:^(id x) {
@synchronized (selfValues) {
[otherValues addObject:x ?: RACTupleNil.tupleNil];
sendNext();
}
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
@synchronized (selfValues) {
otherCompleted = YES;
sendCompletedIfNecessary();
}
}];
return [RACDisposable disposableWithBlock:^{
[selfDisposable dispose];
[otherDisposable dispose];
}];
}] setNameWithFormat:@"[%@] -zipWith: %@", self.name, signal];
}
这个方法的实现看起来很长,但实际上逻辑很简单。它分别订阅了 selfSignal 和 传进来的 otherSignal ,每当两者中任何一个接收到 Next 事件,都会把接收到的 value 存进一个临时数组,同时调用 sendNext
block 👇
void (^sendNext)(void) = ^{
@synchronized (selfValues) {
if (selfValues.count == 0) return;
if (otherValues.count == 0) return;
RACTuple *tuple = RACTuplePack(selfValues[0], otherValues[0]);
[selfValues removeObjectAtIndex:0];
[otherValues removeObjectAtIndex:0];
[subscriber sendNext:tuple];
sendCompletedIfNecessary();
}
};
在这个 block 中,会把两个数组的 firstObject 打包成 RACTuple
,同时它们从数组中移除,并且发送给 Subscriber 。随后调用 sendCompletedIfNecessary
block 👇
void (^sendCompletedIfNecessary)(void) = ^{
@synchronized (selfValues) {
BOOL selfEmpty = (selfCompleted && selfValues.count == 0);
BOOL otherEmpty = (otherCompleted && otherValues.count == 0);
if (selfEmpty || otherEmpty) [subscriber sendCompleted];
}
};
在这个 block 中,会判断两个 Signal 是否已经 Complete 而且没有剩余的 value ,只要有一个 Signal 处于这种状态,就会对 Subscriber 发送 Complete 。