ReactiveCocoa框架学习及资源整理

常用类

RACSignal类

// 创建一个信号
// 每当一个新的subscriber订阅时,会调用didSubscribe
// 内部实现:
// 1. 调用RACDynamicSignal的createSignal:方法,并返回RACDynamicSignal实例对象
// 2. RACDynamicSignal的createSignal:方法内部,首先实例化一个RACDynamicSignal对象,然后将didSubscribe这个block块copy一份保存在_didSubscribe变量中。
+ (RACSignal<ValueType> *)createSignal:(RACDisposable * _Nullable (^)(id<RACSubscriber> subscriber))didSubscribe

RACSignal(Subscription)

// 抽象方法,具体需要由子类去实现。
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber;

// 订阅subscriber的next事件,当subscriber执行next的block后,会执行此处的block
// 方法内部实现:
// 1. 根据传入的参数nextBlock创建RACSubscriber类的实例对象o, 对象o持有nextBlock。
// 2. 调用subscribe:方法,如果调用者是子类RACDynamicSignal对象,会调用其子类方法subscribe:,并返回一个disposable
// 3. RACDynamicSignal的subscribe:方法内部:
// 3.1 创建RACCompoundDisposable对象disposable
// 3.2 根据self, subscriber(对象o),disposable三个参数生成一个RACPassthroughSubscriber对象subscriber,
// 3.3 如果_didSubscribe有值,会使用RACScheduler的subscriptionScheduler方法获取单例对象,并调用schedule:方法,传入一个block参数,该block中会执行_didSubscribe块,并返回一个innerDisposable,添加到disposable中。
- (RACDisposable *)subscribeNext:(void (^)(ValueType _Nullable x))nextBlock;

// 订阅'next'和'completed'事件
- (RACDisposable *)subscribeNext:(void (^)(ValueType _Nullable x))nextBlock completed:(void (^)(void))completedBlock;

// 订阅'next','complete','error'事件
- (RACDisposable *)subscribeNext:(void (^)(ValueType _Nullable x))nextBlock error:(void (^)(NSError * _Nullable error))errorBlock completed:(void (^)(void))completedBlock;

// 订阅'error'事件
- (RACDisposable *)subscribeError:(void (^)(NSError * _Nullable error))errorBlock;

// 订阅'completed'事件
- (RACDisposable *)subscribeCompleted:(void (^)(void))completedBlock;

// 订阅'next','error'事件
- (RACDisposable *)subscribeNext:(void (^)(ValueType _Nullable x))nextBlock error:(void (^)(NSError * _Nullable error))errorBlock;

// 订阅'error', 'complete'事件
- (RACDisposable *)subscribeError:(void (^)(NSError * _Nullable error))errorBlock completed:(void (^)(void))completedBlock;

RACSignal(RACStream)

// 返回一个会立即发送给定value和complete的信号
// 方法内部调用RACReturnSignal类的return:方法
+ (RACSignal<ValueType> *)return:(nullable ValueType)value;

// 返回一个RACEmptySignal信号, 会立即发送complete的信号
+ (RACSignal<ValueType> *)empty; 

// 只改变当前流对象
// 将block懒绑定到接受者的值
// 只有在需要提前终止绑定或关闭某个状态时才应该使用此选项。 -flattenMap:更适合所有其他情况。
// 参数block: 返回RACSignalBindBlock的block。 每次重新评估绑定信号时,都会调用此block。 此block不能为nil或返回nil。
// 返回值: 返回一个新信号,表示所有`block`的惰性应用的组合结果。
- (RACSignal *)bind:(RACSignalBindBlock (^)(void))block;

// 在当前响应流已经完成后,紧接着注入新的响应流
// 当源信号完成时,订阅“signal”。
- (RACSignal *)concat:(RACSignal *)signal;

// 是将不同的流进行打包合成一个流
// 使用给定信号的值将接收器中的值压缩以创建RACTuples。
// 每个信号的第一个“next”将被组合,然后是第二个“next”,依此类推,直到信号完成或出现错误。
// 参数signal: 要压缩的信号,不能为nil
// 返回值: 返回RACTuples的新信号,表示两个信号的组合值。 其中一个原始信号的任何错误都将在返回的信号上转发。
- (RACSignal<RACTwoTuple<ValueType, id> *> *)zipWith:(RACSignal *)signal;

RACSignal(RACStreamOperations)

// 封装bind操作, 将多个流的值映射到接受者上并生成一个新的流
// 将“block”映射到接收器中的值并使结果变平。
// 请注意,在-flattenMap之后应用的运算符与-flattenMap:中的运算符的行为不同。 请参阅下面的示例部分。
// 这对应于Rx中的`SelectMany`方法。
// 参数block: 一个block,它接受接收器中的值并返回接收器类的新实例。 从该block返回“nil”等同于返回空信号。
// 实例:
///   [signal flattenMap:^(id x) {
///       // 每次返回的信号完成时记录。
///       return [[RACSignal return:x] logCompleted];
///   }];
///
///   [[signal
///       flattenMap:^(id x) {
///           return [RACSignal return:x];
///       }]
///       // 所有信号完成后,只记录一次。
///       logCompleted];
// 返回一个新信号,表示映射`block`产生的组合信号。
- (RACSignal *)flattenMap:(__kindof RACSignal * _Nullable (^)(ValueType _Nullable value))block;

// 将多个流拼接为一个流
// 使组合信号变平。
// 对应于Rx中的`Merge`方法。
// 返回由接收器获得的组合信号组成的信号。
- (RACSignal *)flatten;

// 将一个流的值通过转换,映射形成一个新的流
// 这对应于Rx中的“Select”方法。
// 返回带有映射值的新信号。
- (RACSignal *)map:(id _Nullable (^)(ValueType _Nullable value))block;

// 直接使用object替换当前流的值并生成一个新的流
// 为接收器中的每个值返回一个新信号,其中包含给定对象一次。
- (RACSignal *)mapReplace:(nullable id)object;

// 使用block来验证每个值,将验证结果通过的值生成新的流
// 过滤掉未通过给定测试的接收器中的值。
// 这对应于Rx中的`Where`方法。
// 返回仅包含通过的值的新信号。
- (RACSignal<ValueType> *)filter:(BOOL (^)(ValueType _Nullable value))block;

// 忽略和当前值一样的对象,将之变为空流
// 过滤掉接收器中等于(通过-isEqual :)提供的值的值。
// 参数value: 该值可以是“nil”,在这种情况下它会忽略“nil”值。
// 返回一个新信号,其中只包含不等于`value`的值。
- (RACSignal<ValueType> *)ignore:(nullable ValueType)value;

// 将流中的RACTuple对象进行过滤,返回特定的衍生出的一个值对象
// 解压缩接收器中的每个RACTuple并将值映射到新值。
// 参数reduceBlock: 将每个RACTuple的值减少为一个值的block。 它必须采用与要处理的元组元素数量一样多的参数。 每个参数都是一个对象参数。 返回值必须是对象。 这个参数不能是nil。
// 返回减少元组值的新信号。
- (RACSignal *)reduceEach:(RACReduceBlock)reduceBlock;

// 在当前流的值流出之前,加入一个初始值
// 返回由`value`组成的信号,后跟接收器中的值。
- (RACSignal<ValueType> *)startWith:(nullable ValueType)value;

// 忽略当前流前n次的对象值,将之变为空流
// 跳过接收器中的第一个`skipCount`值。
// 跳过第一个`skipCount`值后返回接收器。 如果`skipCount`大于信号中的值的数量,则返回空信号。
- (RACSignal<ValueType> *)skip:(NSUInteger)skipCount;

// 只取当前流中的前n次对象值,之后将流变为空(不是空流)
// 返回接收器中第一个`count`值的信号。 如果`count`大于或等于信号中的值的数量,则返回等效于接收器的信号。
- (RACSignal<ValueType> *)take:(NSUInteger)count;

// 将多个流中的值包装成一个RACTuple对象
// 压缩给定信号中的值以创建RACTuples。
// 将组合每个信号的第一个值,然后组合第二个值,依此类推,直到至少一个信号耗尽。
// 参数signals: 要结合的信号。 如果此集合为空,则返回的信号将为空。
// 返回包含信号中压缩值的RACTuples的新信号。
+ (RACSignal<RACTuple *> *)zip:(id<NSFastEnumeration>)signals;

// 使用+ zip:压缩信号,然后使用-reduceEach将生成的元组减少为单个值:
// 参数signals: 要结合的信号。 如果此集合为空,则返回的信号将为空。
// 参数reduceBlock: 将所有信号的值减少为一个值的block。 它必须采用与给定信号数量一样多的参数。 每个参数都是一个对象参数。 返回值必须是对象。 这个参数不能是nil。
// 实例: 
///   [RACSignal zip:@[ stringSignal, intSignal ]
///       reduce:^(NSString *string, NSNumber *number) {
///           return [NSString stringWithFormat:@"%@: %@", string, number];
///       }];
// 返回一个新信号,其中包含每次调用`reduceBlock`的结果。
+ (RACSignal<ValueType> *)zip:(id<NSFastEnumeration>)signals reduce:(RACGenericReduceBlock)reduceBlock;

// 将新的流拼接到接受者后面
// 返回通过按顺序连接`signals`获得的信号
+ (RACSignal<ValueType> *)concat:(id<NSFastEnumeration>)signals;

// 使用给定的block从左到右组合接收器中的值。
// 算法如下:
// 1. `startingValue`作为`running`值传递给block,接收器的第一个元素作为`next`值传递给block。
// 2. 调用的结果将添加到返回的信号中
// 3. 调用(`running`)的结果和接收器的下一个元素(`next`)被传递给`block`。
// 重复步骤2和3,直到处理完所有值。
// 参数startingValue: 要与接收器的第一个元素组合的值。 该值可能是“nil”。
// 参数reduceBlock: 描述如何组合接收器值的block。 如果接收方为空,则永远不会调用此block。 不能是nil。
// 实例:
///
///      RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence;
///
///      // Contains 1, 3, 6, 10
///      RACSequence *sums = [numbers scanWithStart:@0 reduce:^(NSNumber *sum, NSNumber *next) {
///          return @(sum.integerValue + next.integerValue);
///      }];
// 返回一个由`reduceBlock`的每个应用程序组成的新信号。 如果接收器为空,则返回空信号。
- (RACSignal *)scanWithStart:(nullable id)startingValue reduce:(id _Nullable (^)(id _Nullable running, ValueType _Nullable next))reduceBlock;

// 用同样的block执行每次流中的值,并将结果用于后一次执行当中,每次都把block执行后的值变成新的流中的对象
// 使用给定的block从左到右组合接收器中的值,该block也采用从零开始的值索引。
// 参数startingValue: 要与接收器的第一个元素组合的值。 该值可能是“nil”。
// 参数reduceBlock: 描述如何组合接收器值的block。 此block将从零开始的索引值作为最后一个参数。 如果接收方为空,则永远不会调用此block。 不可能是nil。
// 返回一个由`reduceBlock`的每个应用程序组成的新信号。 如果接收器为空,则返回空信号。
- (RACSignal *)scanWithStart:(nullable id)startingValue reduceWithIndex:(id _Nullable (^)(id _Nullable running, ValueType _Nullable next, NSUInteger index))reduceBlock;

// 将每个先前值和当前值组合到一个对象中。
// 此方法类似于-scanWithStart:reduce:,但只对前一个和当前值(而不是整个信号)进行操作,并且不会将`reduceBlock`的返回值传递给它的下一个调用。
// 参数start: 对于第一个值,该值作为`previous`传递给`reduceBlock`。
// 参数reduceBlock: 将先前值和当前值组合在一起以创建减少值的block。 不能是nil。
// 实例
///      RACSignal<NSNumber *> *numbers = [@[ @1, @2, @3, @4 ].rac_sequence
///          signalWithScheduler:RACScheduler.immediateScheduler];
///
///      // Contains 1, 3, 5, 7
///      RACSignal *sums = [numbers combinePreviousWithStart:@0 reduce:^(NSNumber *previous, NSNumber *next) {
///          return @(previous.integerValue + next.integerValue);
///      }];
// 返回一个新信号,该信号由`reduceBlock`的每个应用程序的返回值组成。
- (RACSignal *)combinePreviousWithStart:(nullable ValueType)start reduce:(id _Nullable (^)(ValueType _Nullable previous, ValueType _Nullable current))reduceBlock;

// 取当前流的对象值,直到当前值满足提供的block,就会将当前流变为空(不是空流)
// 取值直到给定的block返回“YES”。
// 返回接收器中未通过`predicate`的初始值的信号。 如果`predicate`永远不会返回“YES”,则返回与接收器等效的信号。
- (RACSignal<ValueType> *)takeUntilBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 取当前流的对象值,直到当前值不满足提供的block,就会将当前流变为空(不是空流)
// 取值直到给定的block返回“NO”。
// 返回接收器中通过`predicate`的初始值的信号。 如果`predicate`永远不会返回`NO`,则返回等同于接收器的信号。
- (RACSignal<ValueType> *)takeWhileBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 忽略当前流的对象值(变为空流),直到当前值满足提供的block。
// 跳过值,直到给定block返回“YES”。
// 返回一个信号,其中包含接收器的值,这些值遵循任何初始值未通过`predicate`。 如果`predicate`永远不会返回`YES`,则返回一个空信号。
- (RACSignal<ValueType> *)skipUntilBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 忽略当前流的对象值(变为空流),直到当前值不满足提供的block
// 跳过值,直到给定block返回“NO”。
// 返回一个信号,其中包含接收器的值,这些值遵循任何初始值通过`predicate`。 如果`predicate`永远不会返回`NO`,则返回一个空信号。
- (RACSignal<ValueType> *)skipWhileBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 当流中后一次的值和前一次的值不同的时候,才会返回当前值的流,否则返回空流(第一次默认被忽略)
// 返回值的信号 - -isEqual:与前一个值比较时返回NO。
- (RACSignal<ValueType> *)distinctUntilChanged;

RACSignal(Operations)


// 在`next`上执行给定的block。 这应该用于将side effects(副作用)注入信号。
- (RACSignal<ValueType> *)doNext:(void (^)(ValueType _Nullable x))block;

// 在`error`上执行给定的block。 这应该用于将side effects(副作用)注入信号。
- (RACSignal<ValueType> *)doError:(void (^)(NSError * _Nonnull error))block;

// 在`completed`上执行给定的block。 这应该用于将side effects(副作用)注入信号。
- (RACSignal<ValueType> *)doCompleted:(void (^)(void))block;

// 只有当在`interval`秒内没有收到另一个`next`时才发送`next`s。
// 如果接收到“next”,然后在“interval”秒之前接收到另一个“next”,则丢弃第一个值.
// 在自最近的`next`被发送以来已经过了`interval`秒之后,最新的`next`在调度程序上被转发,该值最初被接收。 如果当时+ [RACScheduler currentScheduler]为nil,则使用私有后台调度程序。
// 返回发送限制和延迟的“next”事件的信号。 始终会立即转发完成和错误。
- (RACSignal<ValueType> *)throttle:(NSTimeInterval)interval;

// 当predicate返回YES时节流'next'
// 当predicate为'next'返回YES时:
// 1. 如果在“interval”秒之前接收到另一个“next”,则丢弃先前值。 无论新值是否受到限制,都会发生这种情况。
// 2. 自最初收到值之后经过`interval`秒后,它将在收到它的调度程序上转发。 如果当时+ [RACScheduler currentScheduler]为nil,则使用私有后台调度程序。
// 当`predicate`为`next`返回NO时,它立即被转发,没有任何限制。
// 参数interval: 缓冲传递`predicate`的最新值的秒数。
// 参数predicate: 从接收器传递每个`next`,该block返回是否应该限制给定值。 这个参数不能是nil。
// 返回发送`next`事件的信号,当`predicate`返回YES时受到限制。 始终会立即转发完成和错误。
- (RACSignal<ValueType> *)throttle:(NSTimeInterval)interval valuesPassingTest:(BOOL (^)(id _Nullable next))predicate;

// 在当前调度程序(事件已发送到其上)上延迟“interval”秒后,转发`next`和`completed`事件。
// 如果收到“next”或“completed”时+ [RACScheduler currentScheduler]为nil,则使用私有后台调度程序。
// 返回发送延迟的`next`和`completed`事件的信号。 错误总是立即转发。
- (RACSignal<ValueType> *)delay:(NSTimeInterval)interval;

// 信号完成时重新订阅。
- (RACSignal<ValueType> *)repeat;

// 每次创建订阅时执行给定的块。
// 参数block: 定义订阅side effects的block。 不能是'nil`。
// 实例:
///   // 编写新文件,备份。
///   [[[[fileManager
///       rac_createFileAtPath:path contents:data]
///       initially:^{
///           // 2. 二,备份当前文件
///           [fileManager moveItemAtPath:path toPath:backupPath error:nil];
///       }]
///       initially:^{
///           // 1. 首先,给writeLock加锁。
///           [writeLock lock];
///       }]
///       finally:^{
///           [writeLock unlock];
///       }];
// 返回通过接收器的所有事件的信号,并引入在接收器的任何订阅side effects之前发生的side effects。
- (RACSignal<ValueType> *)initially:(void (^)(void))block;

// 信号完成或错误时执行给定的block。
- (RACSignal<ValueType> *)finally:(void (^)(void))block;

// 将接收器的'next'分成缓冲区,每个缓冲区提供每个'interval'秒。
// 参数interval: 值被分组到一个缓冲区的时间间隔
// 参数scheduler: 返回信号将在其上传递其值的调度程序。 不能是nil或+ [RACScheduler immediateScheduler]。
// 返回一个信号,该信号在`scheduler`上的每个间隔发送缓冲值的RACTuples。 当接收器完成时,将立即发送任何当前缓冲的值。
- (RACSignal<RACTuple *> *)bufferWithTime:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler;

// 将所有接收者的'next'收集到NSArray中。 Nil值将转换为NSNull。
// 这对应于Rx中的`ToArray`方法。
// 返回当接收器成功完成时发送单个NSArray的信号。
- (RACSignal<NSArray<ValueType> *> *)collect;

// 在接收信号完成后接受最后一次`count`'next's。
- (RACSignal<ValueType> *)takeLast:(NSUInteger)count;

// 一旦两者都发送了至少一个`next`,将接收器和给定信号的最新值组合成2元组。
// 任何额外的`next`s将导致一个新的RACTuple,其中包含两个信号的最新值。
// 参数signal: 与之相结合的信号。 这个参数不能是nil。
// 返回发送组合值的RACTuples的信号,转发任何“错误”事件,并在两个输入信号完成时完成。
- (RACSignal<RACTwoTuple<ValueType, id> *> *)combineLatestWith:(RACSignal *)signal;

// 一旦所有信号都发送了至少一个`next`,就将给定信号的最新值合并到RACTuples中。
// 任何额外的`next`s将导致一个新的RACTuple,其中包含所有信号的最新值。
// 参数signals: 与之相结合的信号。如果此集合为空,则返回的信号将在订阅后立即完成。
// 返回发送组合值的RACTuples的信号,转发任何“错误”事件,并在所有输入信号完成时完成。
+ (RACSignal<RACTuple *> *)combineLatest:(id<NSFastEnumeration>)signals;

// 使用+ combineLatest:组合信号,然后使用-reduceEach:将生成的元组减少为单个值。
// 参数signals: 与之相结合的信号。如果此集合为空,则返回的信号将在订阅后立即完成。
// 参数reduceBlock: 将所有信号中的最新值减少为一个值的block。 它必须采用与给定信号数量一样多的参数。 每个参数都是一个对象参数。 返回值必须是对象。 这个参数不能是nil。
// 实例:
///   [RACSignal combineLatest:@[ stringSignal, intSignal ] reduce:^(NSString *string, NSNumber *number) {
///       return [NSString stringWithFormat:@"%@: %@", string, number];
///   }];
// 返回一个信号,该信号发送每次调用`reduceBlock`的结果。
+ (RACSignal<ValueType> *)combineLatest:(id<NSFastEnumeration>)signals reduce:(RACGenericReduceBlock)reduceBlock;

// 用`+ merge:`合并接收器和给定信号并返回结果信号。
- (RACSignal *)merge:(RACSignal *)signal;

// 从任何信号发送最新的`next`。
// 返回一个信号,该信号通过每个给定信号的值,并在所有信号完成时发送`completed`。 如果任何信号发送错误,则返回的信号立即发送“错误”。
+ (RACSignal<ValueType> *)merge:(id<NSFastEnumeration>)signals;

// 将接收器发送的信号合并为扁平信号,但一次只能订阅“maxConcurrent”数量的信号。 当其他信号完成时,新信号排队并订阅。
// 如果任何信号发生错误,则在返回的信号上发送。 它仅在接收器和所有发送信号完成后才完成。
// 参数maxConcurrent:一次订阅的最大信号数。 如果为0,则订阅无限数量的信号。
- (RACSignal *)flatten:(NSUInteger)maxConcurrent;

// 忽略接收器中的所有`next`s,等待接收器完成,然后订阅新信号。
// 参数block: 将创建或获取要订阅的新信号的block,仅在接收器完成后执行。 该block不能为nil,并且不能返回nil信号。
// 返回一个信号,该信号将通过`block`中创建的信号事件。 如果接收器出错,返回的信号也会出错。
- (RACSignal *)then:(RACSignal * (^)(void))block;

// 汇总信号组的内部信号。
- (RACSignal *)concat;

// 将接收器的“next”值聚合为单个组合值。
// 算法如下:
// 1. `start`作为`running`值传递给block,接收器的第一个元素作为`next`值传递给block。
// 2. 调用(`running`)的结果和接收器的下一个元素(`next`)被传递到`reduceBlock`。
// 3. 重复步骤2和3,直到处理完所有值。
// 4. `reduceBlock`的最后一个结果是在返回的信号上发送的。
// 此方法类似于-scanWithStart:reduce:,只是在返回的信号上仅发送最终结果。
// 参数start:要与接收器的第一个元素组合的值。 该值可能是“nil”。
// 参数reduceBlock: 描述如何组合接收器值的block。 如果接收方为空,则永远不会调用此块。 不能是nil。
// 返回一个信号,该信号将在接收器完成时发送聚合值,然后自行完成。 如果接收方从不发送任何值,则会发送“start”。
- (RACSignal *)aggregateWithStart:(id)start reduce:(id (^)(id running, id next))reduceBlock;

// 将接收器的“next”值聚合为单个组合值。 这是-aggregateWithStart:reduce:的索引版本。
// 参数start:要与接收器的第一个元素组合的值。 该值可能是“nil”。
// 参数reduceBlock: 描述如何组合接收器值的block。 此block将从零开始的索引值作为最后一个参数。 如果接收方为空,则永远不会调用此block。 不能是nil。
// 返回一个信号,该信号将在接收器完成时发送聚合值,然后自行完成。 如果接收方从不发送任何值,则会发送“start”。
- (RACSignal *)aggregateWithStart:(id)start reduceWithIndex:(id (^)(id running, id next, NSUInteger index))reduceBlock;

// 将接收器的“next”值聚合为单个组合值。
// 这会在每个订阅上调用`startFactory`block,然后调用-aggregateWithStart:reduce:将block的返回值作为起始值。
// 参数startFactory: 返回将与接收器的第一个元素组合的起始值的block。 不能是nil。
// 参数reduceBlock: 描述如何组合接收器值的block。 如果接收方为空,则永远不会调用此block。 不能是nil。
// 返回一个信号,该信号将在接收器完成时发送聚合值,然后自行完成。 如果接收器从不发送任何值,则将发送`startFactory`的返回值。
- (RACSignal *)aggregateWithStartFactory:(id (^)(void))startFactory reduce:(id (^)(id running, id next))reduceBlock;

// 每隔“interval”秒发送NSDate.date。
// 参数interval: 发送当前时间的时间间隔(以秒为单位)。
// 参数scheduler: 应在其上发送当前NSDate的调度程序。 这不能是nil或+ [RACScheduler immediateScheduler]。
// 返回一个信号,该信号在`scheduler`上每隔“interval”发送当前日期/时间。
+ (RACSignal<NSDate *> *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler;

// 以至少`interval`秒的间隔发送NSDate.date,直到大约`interval` +`leeway`秒。
// 创建的信号将推迟发送每个“next”至少“interval”秒,并为了性能或功耗而延迟额外的“leeway”秒。 请注意,即使指定“余地”为0,也可以预期一些额外的延迟。
// 参数interval: ``next`s之间的基础间隔。
// 参数scheduler: 应在其上发送当前NSDate的调度程序。 这不能是nil或+ [RACScheduler immediateScheduler].
// 参数leeway: “next”可以延迟的最大额外时间。
// 返回一个信号,该信号以至少“interval seconds”的间隔发送当前日期/时间,直到`scheduler`上的大约`interval` +`leeway`秒。
+ (RACSignal<NSDate *> *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler withLeeway:(NSTimeInterval)leeway;

// 采取`next`s直到`signalTrigger`发送`next`或`completed`。
// 返回一个信号,该信号从接收器传递所有事件,直到`signalTrigger`发送`next`或`completed`,此时返回的信号将发送`completed`。
- (RACSignal<ValueType> *)takeUntil:(RACSignal *)signalTrigger;

// 采取`next`s直到`replacement`发送事件。 
// 参数replacement: 一旦发送事件就会替换接收器的信号。
// 返回一个信号,它从接收器传递`next`s和`error`直到`replacement`发送一个事件,此时返回的信号将发送该事件并切换到来自`replacement`的事件,而不管是否 接收者已经发送了事件。
- (RACSignal *)takeUntilReplacement:(RACSignal *)replacement;

// 发生错误时订阅返回的信号。
- (RACSignal *)catch:(RACSignal * (^)(NSError * _Nonnull error))catchBlock;

// 发生错误时订阅给定信号。
- (RACSignal *)catchTo:(RACSignal *)signal;

// 返回一个信号,该信号将立即发送`tryBlock`的返回值并完成,或使用从block传出的`NSError`发生错误。
// 参数tryBlock: 执行某些可能失败的计算的操作。 如果block返回nil,则block必须通过`errorPtr`参数返回错误。
// 实例:
///   [RACSignal try:^(NSError **error) {
///       return [NSJSONSerialization JSONObjectWithData:someJSONData options:0 error:error];
///   }];
+ (RACSignal<ValueType> *)try:(nullable ValueType (^)(NSError **errorPtr))tryBlock;

// 对每个接收者的值运行`tryBlock`,传递值直到`tryBlock`返回NO,或接收者完成。
// 参数tryBlock: 针对每个接收者值运行的操作。 该block应返回YES以指示操作成功。 此block不能为nil。
// 实例:
///   // 如果无法将数据值写入`someFileURL`,则返回的信号将发送错误。
///   [signal try:^(NSData *data, NSError **errorPtr) {
///       return [data writeToURL:someFileURL options:NSDataWritingAtomic error:errorPtr];
///   }];
// 返回一个通过接收器所有值的信号。 如果`tryBlock`对任何值都失败,则返回的信号将使用从block传出的`NSError`错误。
- (RACSignal<ValueType> *)try:(BOOL (^)(id _Nullable value, NSError **errorPtr))tryBlock;

// 对每个接收者的值运行`mapBlock`,映射值直到`mapBlock`返回nil,或者接收者完成。
// 参数mapBlock: 映射每个接收者值的动作。 该block应返回非空值以指示操作成功。 此block不能为nil。
// 实例
///     // 如果无法从`fileURL`读取数据,则返回的信号将发送错误。
///   [signal tryMap:^(NSURL *fileURL, NSError **errorPtr) {
///       return [NSData dataWithContentsOfURL:fileURL options:0 error:errorPtr];
///   }];
// 返回一个转换接收器所有值的信号。 如果`mapBlock`为任何值返回nil,则返回的信号将使用从block传出的`NSError`错误。
- (RACSignal *)tryMap:(id (^)(id _Nullable value, NSError **errorPtr))mapBlock;

// 返回第一个`next`。 请注意,这是一个阻止调用。
- (nullable ValueType)first;

// 如果信号完成则返回第一个`next`或`defaultValue`或返回错误而不发送`next`。 请注意,这是一个阻止调用。
- (nullable ValueType)firstOrDefault:(nullable ValueType)defaultValue;

// 如果信号完成则返回第一个`next`或`defaultValue`或返回错误而不发送`next`。 如果发生错误,则成功将为NO并且将填充错误。 请注意,这是一个阻止调用。
// 成功和错误都可能为NULL。
- (nullable ValueType)firstOrDefault:(nullable ValueType)defaultValue success:(nullable BOOL *)success error:(NSError * _Nullable * _Nullable)error;

// 阻止调用者并等待信号完成。
// 参数error: 如果不为NULL,则设置为发生的任何错误。
// 返回信号是否成功完成。 如果为NO,则将“error”设置为发生的错误。
- (BOOL)waitUntilCompleted:(NSError * _Nullable * _Nullable)error;

// 延迟信号的创建,直到信号实际订阅为止。
// 这可用于有效地将热信号转换为冷信号。
+ (RACSignal<ValueType> *)defer:(RACSignal<ValueType> * (^)(void))block;

// 每次接收器发送一个新的RACSignal时,只为该信号订阅并发送`next`s和'error`s。
// 接收器必须是信号组的一个信号。
// 返回一个信号,该信号从接收器发送的最新信号中通过`next`s和'error`s,并在接收器和最后发送的信号都完成时发送`completed`。
- (RACSignal *)switchToLatest;

// 根据`signal`发送的最新值,在`cases`和`defaultSignal`之间切换信号。
// 参数signal:在`cases`字典中用作键的对象的信号。 这个参数不能是nil。
// 参数cases: 具有信号值的字典。 这个参数不能是nil。 此字典中的RACTupleNil键将匹配在`signal`上接收的nil`next`事件。
// 参数defaultSignal: 在`signal`之后传递的信号发送一个`cases`不包含信号的值。 如果为nil,则任何不匹配的值都将导致RACSignalErrorNoMatchingCase错误。
// 返回一个信号,它通过`case`或`defaultSignal`中的一个信号传递`next`s和`error`,并在`signal`和最后一个使用的信号完成时发送`completed`。 如果没有给出`defaultSignal`,则不匹配的`next`将导致返回信号出错。
+ (RACSignal<ValueType> *)switch:(RACSignal *)signal cases:(NSDictionary *)cases default:(nullable RACSignal *)defaultSignal;

// 根据`boolSignal`发送的最新值在`trueSignal`和`falseSignal`之间切换。
// 参数boolSignal: 确定“trueSignal”或“falseSignal”是否应该激活的BOOL信号。 这个参数不能是nil。
// 参数trueSignal: 在'boolSignal`发送YES后要通过的信号。 这个参数不能是nil。
// 参数falseSignal: 在'boolSignal`发送NO后要通过的信号。 这个参数不能是nil。
// 返回一个信号,该信号从`trueSignal`和/或`falseSignal`传递`next`s和`error`s,并在'boolSignal`和最后一个切换信号完成时发送`completed`。
+ (RACSignal<ValueType> *)if:(RACSignal<NSNumber *> *)boolSignal then:(RACSignal *)trueSignal else:(RACSignal *)falseSignal;

// 将每个`next`添加到数组中。 Nils由NSNulls代表。 请注意,这是一个阻止调用。
// 返回`next`值的数组,如果发生错误,则返回nil。
- (nullable NSArray<ValueType> *)toArray;

// 将每个`next`添加到序列中。 Nils由NSNulls代表。
// 返回一个序列,在发送信号时提供信号的值。 尝试从尚未发送的序列中检索值将阻止。
@property (nonatomic, strong, readonly) RACSequence<ValueType> *sequence;;

// 创建并返回多播连接。 这允许您共享对基础信号的单个订阅。
- (RACMulticastConnection<ValueType> *)publish;

// 创建并返回将值推送到给定subject的多播连接。 这允许您共享对基础信号的单个订阅。
- (RACMulticastConnection<ValueType> *)multicast:(RACSubject<ValueType> *)subject;

// 将信号多播到无限容量的RACReplaySubject,并立即连接到生成的RACMulticastConnection。
// 返回连接的多播信号。
- (RACSignal<ValueType> *)replay;

// 将信号多播到容量为1的RACReplaySubject,并立即连接到生成的RACMulticastConnection。
// 返回连接的多播信号。
- (RACSignal<ValueType> *)replayLast;

// 将信号多播到无限容量的RACReplaySubject,并且延迟地连接到生成的RACMulticastConnection。
// 这意味着只有当前者收到第一个订阅时,返回的信号才会订阅多播信号。
// 返回延迟连接的多播信号。
- (RACSignal<ValueType> *)replayLazily;

// 如果在此之前源未完成,则在“interval”秒后发送错误。
// 错误将在RACSignalErrorDomain中,并且代码为RACSignalErrorTimedOut。
// 参数interval: 信号出错之前的秒数。
// 参数scheduler: 应该发送任何超时错误的调度程序。 这不能是nil或+ [RACScheduler immediateScheduler]。
// 返回通过接收者事件的信号,直到流完成或超时,此时将在`scheduler`上发送错误。
- (RACSignal<ValueType> *)timeout:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler;

// 创建并返回在给定调度程序上传递其事件的信号。 接收器的任何side effects仍将在原始线程上执行。
// 当信号已经在所需的线程上执行其工作,但您希望在其他地方处理其事件时,这是理想的。
- (RACSignal<ValueType> *)deliverOn:(RACScheduler *)scheduler;

// 创建并返回执行其side effects的信号,并在给定的调度程序上传递其事件。
// 应尽可能避免使用此运算符,因为接收器的side effects在另一个线程上运行可能不安全。 如果您只想在`scheduler`上接收信号的事件,请使用-deliverOn:代替。
- (RACSignal<ValueType> *)subscribeOn:(RACScheduler *)scheduler;

// 创建并返回在主线程上传递其事件的信号。 如果事件已经在主线程上发送,则可以毫不拖延地传递它们。 如果在另一个线程上发送,或者如果先前的事件已在处理或已排队,则事件将排队等待以后在主线程上传递。
// 接收器的任何side effects仍将在原始线程上执行。
// 当信号将导致UI更新时,可以使用此方法,以避免由延迟传递事件(例如视图实例化时RACObserve中的第一个事件)引起的潜在闪烁。
- (RACSignal<ValueType> *)deliverOnMainThread;

// 将每个接收到的对象分组到一个组中,通过使用该对象调用“keyBlock”来确定。 通过使用对象调用`transformBlock`来转换发送的对象。 如果`transformBlock`为nil,则发送原始对象。
// 返回的信号是RACGroupedSignal的信号。
- (RACSignal<RACGroupedSignal *> *)groupBy:(id<NSCopying> _Nullable (^)(id _Nullable object))keyBlock transform:(nullable id _Nullable (^)(id _Nullable object))transformBlock;

// 调用-[RACSignal groupBy:keyBlock transform:nil].
- (RACSignal<RACGroupedSignal *> *)groupBy:(id<NSCopying> _Nullable (^)(id _Nullable object))keyBlock;

// 如果接收信号发送任何对象,则发送[NSNumber numberWithBool:YES]。
- (RACSignal<NSNumber *> *)any;

// 如果接收信号发送任何通过`predicateBlock`的对象,则发送[NSNumber numberWithBool:YES]。
// 参数predicateBlock - 不能为nil.
- (RACSignal<NSNumber *> *)any:(BOOL (^)(id _Nullable object))predicateBlock;

// 如果接收信号发送的所有对象都通过`predicateBlock`,则发送[NSNumber numberWithBool:YES]。
// 参数predicateBlock - 不能为nil.
- (RACSignal<NSNumber *> *)all:(BOOL (^)(id _Nullable object))predicateBlock;

// 如果发生错误,则重新订阅接收信号,直到重试给定次数为止。
// 参数retryCount: 如果为0,它会一直重试,直到完成。
- (RACSignal<ValueType> *)retry:(NSInteger)retryCount;

// 如果发生错误,则重新订阅接收信号。
- (RACSignal<ValueType> *)retry;

// 仅当“sampler”发送值时才从接收器发送最新值。 如果`sampler`比接收器更频繁地触发,则返回的信号可以重复值。 来自`sampler`的值在接收器发送其第一个值之前被忽略。
// 参数sampler: 控制何时发送来自接收器的最新值的信号。 不能为nil。
- (RACSignal<ValueType> *)sample:(RACSignal *)sampler;

// 忽略接收器中的所有‘next’。
// 返回仅从接收器传递“error”或“completed”事件的信号。
- (RACSignal *)ignoreValues;

// 将每个接收者的事件转换为RACEvent对象。
// 返回一个信号,它将接收者的事件作为RACEvents发送,并在接收者发送“completed”或“error”后完成。
- (RACSignal<RACEvent<ValueType> *> *)materialize;

// 将接收器中的每个RACEvent转换回“真正的”RACSignal事件。
// 返回一个信号,为每个值RACEvent发送`next`,为每个错误RACEvent发送`error`,为每个完成的RACEvent发送`completed`。
- (RACSignal *)dematerialize;

// 反转接收器发送的每个NSNumber包装的BOOL。 如果接收者发送除NSNumbers之外的任何内容,它将断言。
// 返回反转的NSNumber包装的BOOL的信号。
- (RACSignal<NSNumber *> *)not;

// 在接收方发送的所有NSNumbers的RACTuple上执行AND。
// 如果接收方发送除一个或多个NSNumber的RACTuple之外的任何内容,则断言。
// 返回一个信号,该信号对元组中的每个NSNumber应用AND。
- (RACSignal<NSNumber *> *)and;

//在接收方发送的所有NSNumbers的RACTuple上执行OR
// 如果接收方发送除一个或多个NSNumber的RACTuple之外的任何内容,则断言。
// 返回一个信号,该信号对元组中的每个NSNumber应用OR。
- (RACSignal<NSNumber *> *)or;

// 使用接收器发送的每个RACTuple中打包的参数发送调用块的结果。
// 接收器必须发送元组值,其中元组的第一个元素是块,取多个参数等于元组的其余元素的计数,并返回一个对象。 每个块必须至少有一个参数,因此每个元组必须包含至少2个元素。
// 实例:
///   RACSignal *adder = [RACSignal return:^(NSNumber *a, NSNumber *b) {
///       return @(a.intValue + b.intValue);
///   }];
///   RACSignal *sums = [[RACSignal
///       combineLatest:@[ adder, as, bs ]]
///       reduceApply];
// 返回将每个元组的第一个元素应用于其余元素的结果的信号。
- (RACSignal *)reduceApply;

RACSubscriber

  • RACSubscriber.h 文件 -> RACSubscriber协议
  • RACSubscriber.m 文件 -> RACSubscriber类的扩展以及实现代码
  • RACSubscriber+Private.h 文件 -> RACSubscriber类的头文件

注意: RACSubscriber类 遵守 RACSubscriber协议

RACSubscriber协议四个必须实现的方法
- sendNext:
- sendError:
- sendCompleted
- didSubscribeWithDisposable:

// 给订阅者subscribers发送next value
- (void)sendNext:(nullable id)value;

// 给订阅者subscribers发送一个error
// 会立即终止subscription,并且使subscriber作废, 也就是说subscriber将不能订阅任何事情
- (void)sendError:(nullable NSError *)error;

// 给订阅者subscribers发送completed
// 会立即终止subscription,并且使subscriber作废, 也就是说subscriber将不能订阅任何事情
- (void)sendCompleted;

// 给订阅者subscriber发送一个disposable
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;

RACSubscriber类遵守了RACSubscriber协议
RACSubscriber类

// 实例化方法
// 根据给定的next, error, completed参数创建一个subscriber
// 类的扩展中包含next, error, completed三个block属性用于保存初始化时传递进来的三个参数,和一个只读的disposable属性,初始化的时候回创建一个disposable(RACCompoundDisposable类)。
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed;

// 协议方法的实现
// 调用保存的next这个block块
- (void)sendNext:(id)value {...}

// 1. 调用self.disposable的dispose方法
// 2. 调用保存的error这个block块
- (void)sendError:(NSError *)e {...}

// 1. 调用self.disposable的dispose方法
// 2. 调用保存的completed这个block块
- (void)sendCompleted {...}

// 1. 给self.disposable添加一个otherDisposable
// 2. otherDisposable添加一个新创建的RACDisposable实例,并在创建时的block中,将otherDisposable从self.disposable中移除,避免内存无限增加。
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)otherDisposable {...}

RACCommand

通常,Command是响应某些动作而触发的信号

属性

// 成功调用-execute返回的信号的信号:(即接收者“启用”时)。
// 错误将自动捕获内部信号,并在“errors”上发送。 如果要接收内部错误,请使用-execute:或 - [RACSignal materialize]。
// 只有在订阅之后的执行将根据此信号发送。所有内部信号都将达到主线程
@property (nonatomic, strong, readonly) RACSignal<RACSignal<ValueType> *> *executionSignals;

// 发送这条命令是否正在执行的信号
// 每当调用-execute:并且创建的信号尚未终止时,这将发送YES。 一旦所有执行终止,`executing`将发送NO。
// 此信号将在订阅时发送其当前值,然后在主线程上发送所有未来值。
@property (nonatomic, strong, readonly) RACSignal<NSNumber *> *executing;

// 发送这条命令是否能够执行的信号
// 出现以下情况时会发送NO:
// 1. 该命令是使用`enabledSignal`创建的,并且在该信号上发送NO,
// 2. “allowsConcurrentExecution”为NO且命令已开始执行。
// 一旦不再满足上述条件,信号将发送YES。
// 此信号将在订阅时发送其当前值,然后在主线程上发送所有未来值。
@property (nonatomic, strong, readonly) RACSignal<NSNumber *> *enabled;

// 转发-execute:返回的信号中发生的任何错误。
// 当从-execute:返回的信号发生错误时,该信号将相关的NSError值作为“next”事件发送(因为`error`事件将终止该流)。
// 订阅后,此信号将在主线程上发送所有未来错误。
@property (nonatomic, strong, readonly) RACSignal<NSError *> *errors;

// 这条命令是否允许多个执行同时进行。默认为NO
@property (atomic, assign) BOOL allowsConcurrentExecution;

方法

// 调用下面的方法,enabledSignal传nil 
- (instancetype)initWithSignalBlock:(RACSignal<ValueType> * (^)(InputType _Nullable input))signalBlock;

// 根据条件初始化一个command
// 参数:
// enabledSignal: BOOL值的信号,指示是否应该启用命令。 `enabled`将基于此信号发送的最新值。 在发送任何值之前,`enabled`将默认为YES。 这个参数可能是nil。
// signalBlock: 一个block,它将每个输入值(传递给-execute :)映射到工作信号。 返回的信号将被多播到replay subject,在`executionSignals`上发送,然后同步订阅。 block和返回的信号都不为nil。
- (instancetype)initWithEnabled:(nullable RACSignal<NSNumber *> *)enabledSignal signalBlock:(RACSignal<ValueType> * (^)(InputType _Nullable input))signalBlock;

// 如果接受者是enabled,将:
// 1. 调用初始化时给出的signalBlock
// 2. 将返回的信号多播到RACReplaySubject。
// 3. 在`executionSignals`上发送多播信号。
// 4. 订阅(连接)主线程上的原始信号。
// 
// 参数input: 传递给接收者的`signalBlock`的输入值。 这可能是零
// 订阅后返回多播信号。如果接受者不是enabled,则返回一个发送代码为RACCommandErrorNotEnabled错误的信号。
- (RACSignal<ValueType> *)execute:(nullable InputType)input;

RACDisposable

负责清除订阅所需的工作

// 接收器是否已被丢弃。
// 不鼓励使用此属性,因为它可以在任何时间同时设置为“是”
// 此属性不符合KVO标准。
@property (atomic, assign, getter = isDisposed, readonly) BOOL disposed;

// 初始化
+ (instancetype)disposableWithBlock:(void (^)(void))block;

// 执行清理工作。 可以多次调用,但后续调用不会执行任何操作。
- (void)dispose;

// 返回一个新的Disposable,当它被销毁时会丢弃。
- (RACScopedDisposable *)asScopedDisposable;

RACSequence类

RACSequence

// 序列中的第一个对象,如果序列为空,则为nil。
// 子类必须提供此方法的实现。
@property (nonatomic, strong, readonly, nullable) ValueType head;

// 除序列中的第一个对象外的所有对象,如果没有其他对象,则为nil。
// 子类必须提供此方法的实现。
@property (nonatomic, strong, readonly, nullable) RACSequence<ValueType> *tail;

// 评估完整序列以生成等效大小的数组。
@property (nonatomic, copy, readonly) NSArray<ValueType> *array;

// 返回序列中所有对象的枚举器。
@property (nonatomic, copy, readonly) NSEnumerator<ValueType> *objectEnumerator;

// 将序列转换为急切序列。
// 急切的序列会立即全面评估其所有值。 来自急切序列的序列也将非常渴望。
// 返回一个新的急切序列,如果序列已经急切,则返回接收者。
@property (nonatomic, copy, readonly) RACSequence<ValueType> *eagerSequence;

// 将序列转换为延迟序列。
// 延迟序列在访问它们时按需评估其值。 衍生自惰性序列的序列也是惰性的。
// 返回一个新的延迟序列,如果序列已经是惰性的,则返回接收者。
@property (nonatomic, copy, readonly) RACSequence<ValueType> *lazySequence;

// 使用新的RACScheduler调用-signalWithScheduler:。
- (RACSignal<ValueType> *)signal;

// 评估给定调度程序的完整序列。
// 每个项目在其自己的调度块中进行评估,以便在每个值之间产生对调度程序的控制。
// 返回一个信号,该信号在给定的调度程序进行评估时发送接收器的值。
- (RACSignal<ValueType> *)signalWithScheduler:(RACScheduler *)scheduler;

// 对序列应用左折叠。
// 这与迭代序列以及提供的起始值相同。 这使用恒定的内存量。 左侧折叠是左关联的,因此在序列[1,2,3]中,块将按以下顺序应用:reduce(reduce(reduce(start,1),2),3)
// 参数start: 折叠的起始值。 用作第一次折叠的“累加器”。
// 参数reduce: 用于组合累计值和下一个值的block。不能为nil
// 返回减少的值
- (id)foldLeftWithStart:(nullable id)start reduce:(id _Nullable (^)(id _Nullable accumulator, ValueType _Nullable value))reduce;

// 对序列应用右折叠。
// 右侧折叠相当于列表中的递归。 该列从列表中的右侧到左侧进行评估。 它是右关联的,所以它首先应用于最右边的元素。 例如,在序列[1,2,3]中,块按以下顺序应用:reduce(1,reduce(2,reduce(3,start)))
// 参数start: 折叠的起始值。
// 参数reduce: 用于组合累计值和下一个头的块。 该块被赋予累积值和其余计算的值(递归的结果)。 使用`rest.head`检索其值时计算。 如果您不需要,可以通过不访问`rest.head`来防止不必要的计算。
// 返回减少的值
- (id)foldRightWithStart:(nullable id)start reduce:(id _Nullable (^)(id _Nullable first, RACSequence *rest))reduce;

// 检查序列中的任何值是否通过block。
// 参数block: block谓词用于检查每个项目,不能为nil。
// 返回一个布尔值,指示序列中是否传递了任何值
- (BOOL)any:(BOOL (^)(ValueType _Nullable value))block;

// 检查序列中的所有值是否都通过了block。
// 参数block: block谓词用于检查每个项目,不能为nil。
// 返回一个布尔值,指示序列中是否传递了所有值
- (BOOL)all:(BOOL (^)(ValueType _Nullable value))block;

// 返回通过block的第一个对象。
// 参数block: block谓词用于检查每个项目,不能为nil。
// 如果有通过block则返回通过的第一个对象,如果没有对象通过则返回nil 
- (nullable ValueType)objectPassingTest:(BOOL (^)(ValueType _Nullable value))block;

// 创建一个动态生成其值的序列。
// 参数headBlock: 第一次调用-head被访问。
// 参数tailBlock: 第一次调用-tail被访问。
// 每个块的结果都被记忆,因此无论访问序列的头部和尾部属性多次,每个块最多只会被调用一次。
// `headBlock`或`tailBlock`中的任何side effects都应该是线程安全的,因为可以在任何时候从任何线程计算序列。 不仅如此,可以在-head之前访问-tail,或者可以同时访问两者。 如上所述,side effects仅在第一次触发-head或触发-tail时触发。
+ (RACSequence<ValueType> *)sequenceWithHeadBlock:(ValueType _Nullable (^)(void))headBlock tailBlock:(nullable RACSequence<ValueType> *(^)(void))tailBlock;

RACSequence(RACStream)

// 返回立即发送给定值然后完成的序列。
+ (RACSequence<ValueType> *)return:(nullable ValueType)value;

// 返回立即完成的序列。
+ (RACSequence<ValueType> *)empty;

// 一个block,它接受来自RACSequence的值并返回一个新序列。
// 将`stop`设置为`YES`将导致绑定在返回值后终止。 返回“nil”将导致立即终止。
typedef RACSequence * _Nullable (^RACSequenceBindBlock)(ValueType _Nullable value, BOOL *stop);

// 延迟地将block绑定到接收器中的值。
// 只有在需要提前终止绑定或关闭某个状态时才应该使用此选项。 -flattenMap:更适合所有其他情况。
// 参数block: 返回RACSequenceBindBlock的block。 每次重新评估绑定序列时,都会调用此block。 此块不能为nil或返回nil。
// 返回一个新序列,它表示`block`的所有惰性应用程序的组合结果。
- (RACSequence *)bind:(RACSequenceBindBlock (^)(void))block;

// 源序列完成时订阅`sequence`
- (RACSequence *)concat:(RACSequence *)sequence;

// 使用给定序列的值将接收器中的值压缩以创建RACTuples。
// 每个序列的第一个“next”将被组合,然后是第二个“next”,依此类推,直到任一序列完成或错误。
// 参数sequence: 用来压缩的序列,不能为nil
// 返回RACTuples的新序列,表示两个序列的组合值。 原始序列之一的任何错误都将在返回的序列上转发。
- (RACSequence<RACTuple *> *)zipWith:(RACSequence *)sequence;

RACStream(RACStreamOperations)

// 将“block”映射到接收器中的值并使结果变平。
// 参数block: 一个block,它接受接收器中的值并返回接收器类的新实例。 从这个block返回`nil`相当于返回一个空序列。
// 返回一个新序列,表示映射`block`得到的组合序列。
- (RACSequence *)flattenMap:(__kindof RACSequence * _Nullable (^)(ValueType _Nullable value))block;

// 是组合序列变平
// 返回由从接收器获得的组合序列组成的序列。
- (RACSequence *)flatten;

// 通过block来映射序列
// 返回带有映射值的新序列
- (RACSequence *)map:(id _Nullable (^)(ValueType _Nullable value))block;

// 用给定对象替换接收器中的每个值。
// 返回一个新序列,该序列包含接收器中每个值的给定对象一次。
- (RACSequence *)mapReplace:(nullable id)object;

// 过滤掉未通过给定测试的接收器中的值。
// 返回仅包含通过的值的新序列。
- (RACSequence<ValueType> *)filter:(BOOL (^)(id _Nullable value))block;

// 过滤掉接收器中等于(通过-isEqual :)提供的值的值。
// 返回一个新序列,仅包含不等于`value`的值。
- (RACSequence *)ignore:(nullable ValueType)value;

// 解压缩接收器中的每个RACTuple并将值映射到新值。
// 参数reduceBlock: 将每个RACTuple的值减少为一个值的block。 它必须采用与要处理的元组元素数量一样多的参数。 每个参数都是一个对象参数。 返回值必须是对象。 这个参数不能是nil。
// 返回减少的元组值的新序列。
- (RACSequence *)reduceEach:(RACReduceBlock)reduceBlock;

// 返回由`value`组成的序列,后跟接收器中的值。
- (RACSequence<ValueType> *)startWith:(nullable ValueType)value;

// 跳过接收器中的第一个`skipCount`值。
// 跳过第一个`skipCount`值后返回接收器。 如果`skipCount`大于序列中的值的数量,则返回空序列。
- (RACSequence<ValueType> *)skip:(NSUInteger)skipCount;

// 返回接收器中第一个`count`值的序列。 如果`count`大于或等于序列中的值的数量,则返回等同于接收器的序列。
- (RACSequence<ValueType> *)take:(NSUInteger)count;

// 压缩给定序列中的值以创建RACTuples。
// 将组合每个序列的第一个值,然后组合第二个值,依此类推,直到至少一个序列耗尽。
// 参数sequences: 要结合的序列。 如果此集合为空,则返回的序列将为空。
// 返回包含序列中压缩值的RACTuples的新序列。
+ (RACSequence<RACTuple *> *)zip:(id<NSFastEnumeration>)sequence;

// 使用+ zip:压缩序列,然后使用-reduceEach:将生成的元组减少为单个值。
// 参数sequences: 要结合的序列。 如果此集合为空,则返回的序列将为空。
// 参数reduceBlock: 将所有序列的值减少为一个值的block。 它必须采用与给定序列数一样多的参数。 每个参数都是一个对象参数。 返回值必须是对象。 这个参数不能是nil。
// 实例:
///   [RACSequence zip:@[ stringSequence, intSequence ]
///       reduce:^(NSString *string, NSNumber *number) {
///           return [NSString stringWithFormat:@"%@: %@", string, number];
///       }];
// 返回一个新序列,其中包含每次调用`reduceBlock`的结果。
+ (RACSequence<ValueType> *)zip:(id<NSFastEnumeration>)sequences reduce:(RACReduceBlock)reduceBlock;
+ 
// 返回通过按顺序连接“sequences”获得的序列。
+ (RACSequence<ValueType> *)concat:(id<NSFastEnumeration>)sequences;

// 使用给定的block从左到右组合接收器中的值。
// 算法如下:
// 1. `startingValue`作为`running`值传递给block,接收器的第一个元素作为`next`值传递给block。
// 2. 调用的结果将添加到返回的序列中。
// 3. 调用(`running`)的结果和接收器的下一个元素(`next`)被传递给`block`。
// 4. 重复步骤2和3,直到处理完所有值。
// 参数startingValue: 要与接收器的第一个元素组合的值。 该值可能是“nil”。
// 参数reduceBlock: 描述如何组合接收器值的block。 如果接收方为空,则永远不会调用此block。 不能是nil。
// 实例:
///      RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence;
///
///      // Contains 1, 3, 6, 10
///      RACSequence *sums = [numbers scanWithStart:@0 reduce:^(NSNumber *sum, NSNumber *next) {
///          return @(sum.integerValue + next.integerValue);
///      }];
// 返回一个由`reduceBlock`的每个应用程序组成的新序列。 如果接收器为空,则返回空序列。
- (RACSequence *)scanWithStart:(nullable id)startingValue reduce:(id _Nullable (^)(id _Nullable running, ValueType _Nullable next))reduceBlock;

// 使用给定的block从左到右组合接收器中的值,该block也采用从零开始的值索引。
// 参数startingValue: 要与接收器的第一个元素组合的值。 该值可能是“nil”。
// 参数reduceBlock: 描述如何组合接收器值的block。 此block将从零开始的索引值作为最后一个参数。 如果接收方为空,则永远不会调用此block。 不能是nil。
// 返回一个由`reduceBlock`的每个应用程序组成的新序列。如果接收器为空,则返回空序列。
- (RACSequence *)scanWithStart:(nullable id)startingValue reduceWithIndex:(id _Nullable (^)(id _Nullable running, ValueType _Nullable next, NSUInteger index))reduceBlock;

// 将每个先前值和当前值组合到一个对象中。
// 此方法类似于-scanWithStart:reduce:,但只对前一个和当前值(而不是整个序列)进行操作,并且不会将`reduceBlock`的返回值传递给它的下一个调用。
// 参数start: 对于第一个值,该值作为`previous`传递给`reduceBlock`。
// 参数reduceBlock: 将先前值和当前值组合在一起以创建减少值的block。 不能是nil。
// 实例:
///      RACSequence *numbers = [@[ @1, @2, @3, @4 ].rac_sequence;
///
///      // Contains 1, 3, 5, 7
///      RACSequence *sums = [numbers combinePreviousWithStart:@0 reduce:^(NSNumber *previous, NSNumber *next) {
///          return @(previous.integerValue + next.integerValue);
///      }];
// 返回一个新序列,该序列由`reduceBlock`的每个应用程序的返回值组成。
- (RACSequence *)combinePreviousWithStart:(nullable ValueType)start reduce:(id _Nullable (^)(ValueType _Nullable previous, ValueType _Nullable current))reduceBlock;

// 取值直到给定的block返回“YES”。
// 返回接收器中未通过`predicate`的初始值的RACSequence。 如果`predicate`永远不会返回`YES`,则返回与接收器等效的序列。
- (RACSequence<ValueType> *)takeUntilBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 取值直到给定的block返回“NO”。
// 返回接收器中通过`predicate`的初始值的RACSequence。 如果`predicate`永远不会返回`NO`,则返回与接收器等效的序列。
- (RACSequence<ValueType> *)takeWhileBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 跳过值,直到给定block返回“YES”。
// 返回一个序列,其中包含接收器的值,这些值遵循任何初始值未通过`predicate`。 如果`predicate`永远不会返回`YES`,则返回一个空序列。
- (RACSequence<ValueType> *)skipUntilBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 跳过值,直到给定block返回“NO”。
// 返回一个序列,其中包含接收器的值,这些值遵循任何初始值通过`predicate`。 如果`predicate`永远不会返回`NO`,则返回一个空序列。
- (RACSequence<ValueType> *)skipWhileBlock:(BOOL (^)(ValueType _Nullable x))predicate;

// 返回-isEqual:与前一个值比较时返回NO的值序列。
- (RACSequence<ValueType> *)distinctUntilChanged;

常用宏

RAC(TARGET, ...)

RACSubscriptingAssignmentTrampoline.h文件中定义。

// 将信号分配给对象属性,自动在每个“next”上设置给定的键路径。 信号完成后,绑定将自动清理。
// 这个宏有两个不同的版本:
// 1.RAC(TARGET, KEYPATH, NILVALUE): RAC(TARGET, KEYPATH, NILVALUE)将`TARGET`的`KEYPATH`绑定到给定信号。 如果信号发送'nil`值,则属性将设置为“NILVALUE”。 对于对象属性,`NILVALUE`本身可能是'nil`,但是NSValue应该用于原始属性,以避免在发送`nil`时发生异常。
// 2.RAC(TARGET, KEYPATH): RAC(TARGET, KEYPATH)与上面的相同,但是`NILVALUE`默认为`nil`。
// 实例:
///  RAC(self, objectProperty) = objectSignal;
///  RAC(self, stringProperty, @"foobar") = stringSignal;
///  RAC(self, integerProperty, @42) = integerSignal;
// 注意: 在某些情况下,使用此宏可能是线程不安全的。
#define RAC(TARGET, ...) \
    metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \
        (RAC_(TARGET, __VA_ARGS__, nil)) \
        (RAC_(TARGET, __VA_ARGS__))

/// Do not use this directly. Use the RAC macro above.
#define RAC_(TARGET, KEYPATH, NILVALUE) \
    [[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(TARGET) nilValue:(NILVALUE)][@keypath(TARGET, KEYPATH)]

RACObserve(TARGET, KEYPATH)

NSObject+RACPropertySubscribing.h文件中定义
注意: RACObserve隐式引用了self,在使用时注意防止循环引用造成内存泄漏的问题。

// 创建一个信号,在“TARGET”上观察“KEYPATH”的变化。
// 在任何一种情况下,观察一直持续到“TARGET”或者self被销毁。 如果替代销毁任何中间对象,则假定它已设置为nil。
// 在block中使用此宏时,确保`@strongify(self)`! 宏将始终引用`self`,它可以在block中静默引入保留循环。 因此,在使用`RACObserve`的表达式之前,应该确保`self`是一个弱引用(例如,由`@ weakify`和`@ strongify`创建)。
// 实例:
///    // 观察 self, 直到self被销毁.
///    RACSignal *selfSignal = RACObserve(self, arrayController.items);
///
///    // 观察self.arrayController,直到self或arrayController被销毁
///    RACSignal *arrayControllerSignal = RACObserve(self.arrayController, items);
///
///    // 观察 obj.arrayController, 直到self或arrayController被销毁
///    RACSignal *signal2 = RACObserve(obj.arrayController, items);
///
///    @weakify(self);
///    RACSignal *signal3 = [anotherSignal flattenMap:^(NSArrayController *arrayController) {
///        // 由于RACObserve隐式引用了self,因此要防止循环引用
///        @strongify(self);
///        return RACObserve(arrayController, items);
///    }];
#define _RACObserve(TARGET, KEYPATH) \
({ \
    __weak id target_ = (TARGET); \
    [target_ rac_valuesForKeyPath:@keypath(TARGET, KEYPATH) observer:self]; \
})

#if __clang__ && (__clang_major__ >= 8)
#define RACObserve(TARGET, KEYPATH) _RACObserve(TARGET, KEYPATH)
#else
#define RACObserve(TARGET, KEYPATH) \
({ \
    _Pragma("clang diagnostic push") \
    _Pragma("clang diagnostic ignored \"-Wreceiver-is-weak\"") \
    _RACObserve(TARGET, KEYPATH) \
    _Pragma("clang diagnostic pop") \
})
#endif

ReactiveCococa优质学习资源(排名不分先后)

美团技术团队-ReactiveCocoa核心元素与信号流
美团技术团队-ReactiveCocoa中潜在的内存泄漏及解决方案
美团技术团队-细说ReactiveCocoa的冷信号与热信号(三):怎么处理冷信号与热信号
美团技术团队-细说ReactiveCocoa的冷信号与热信号(二):为什么要区分冷热信号
美团技术团队-细说ReactiveCocoa的冷信号与热信号(一)
美团技术团队-RACSignal的Subscription深入分析
唐巧-ReactiveCocoa 讨论会
唐巧-ReactiveCocoa - iOS开发的新框架
NSHisper-Reactive​Cocoa
戴铭-从 ReactiveCocoa 中能学到什么?不用此库也能学以致用
戴铭-iOS函数响应式编程以及ReactiveCocoa的使用
戴铭-使用ReactiveCocoa开发RSS阅读器
sunnyxx-Reactive Cocoa Tutorial 4 = 只取所需的Filters
sunnyxx-Reactive Cocoa Tutorial 3 = RACSignal的巧克力工厂
sunnyxx-Reactive Cocoa Tutorial 2 = 百变RACStream
sunnyxx-Reactive Cocoa Tutorial 1 = 神奇的Macros
sunnyxx-Reactive Cocoa Tutorial 0 = Overview
一缕殇流化隐半边冰霜-ReactiveCocoa 中 RACSignal 是如何发送信号的
一缕殇流化隐半边冰霜-ReactiveCocoa 中 RACSignal 所有变换操作底层实现分析(上)
一缕殇流化隐半边冰霜-ReactiveCocoa 中 RACSignal 所有变换操作底层实现分析(中)
一缕殇流化隐半边冰霜-ReactiveCocoa 中 RACSignal 所有变换操作底层实现分析(下)
一缕殇流化隐半边冰霜-ReactiveCocoa 中 RACSignal 冷信号和热信号底层实现分析
一缕殇流化隐半边冰霜-ReactiveCocoa 中 集合类RACSequence 和 RACTuple底层实现分析
一缕殇流化隐半边冰霜-ReactiveCocoa 中 RACScheduler是如何封装GCD的
一缕殇流化隐半边冰霜-ReactiveCocoa 中 RACCommand底层实现分析
一缕殇流化隐半边冰霜-ReactiveCocoa 中 奇妙无比的“宏”魔法
袁峥-最快让你上手ReactiveCocoa之基础篇
袁峥-最快让你上手ReactiveCocoa之进阶篇
limboy-ReactiveCocoa2实战
limboy-说说ReactiveCocoa 2
limboy-ReactiveCocoa与Functional Reactive Programming
Draveness-『状态』驱动的世界:ReactiveCocoa
Draveness-Pull-Driven 的数据流 RACSequence
Draveness-『可变』的热信号 RACSubject
Draveness-优雅的 RACCommand
Draveness-用于多播的 RACMulticastConnection
Draveness-RAC 中的双向数据绑定 RACChannel
Draveness-理解 RACScheduler 的实现
Draveness-从代理到 RACSignal
杨萧玉-ReactiveCocoa 和 MVVM 入门
南峰子-ReactiveCocoa Tutorial – The Definitive Introduction: Part 1/2
南峰子-ReactiveCocoa Tutorial – The Definitive Introduction: Part 2/2
南峰子-MVVM Tutorial with ReactiveCocoa: Part 1/2
南峰子-MVVM Tutorial with ReactiveCocoa: Part 2/2
南峰子-Binding To A UITableView From A ReactiveCocoa ViewModel

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容