信号类基础概念及原理

信号类的集成关系图

IMAGE

RACSrteam

  • 解释:所有信号的父类
  • 作用:建立信号之间的链接,例如map/filter/zip函数
  • 使用案例:一般情况下,我们不需要去创建它,直接创建会抛出异常。
1
2
3
4
5
// 已Empty为例。
+ (__kindof RACStream *)empty {
NSString *reason = [NSString stringWithFormat:@"%@ must be overridden by subclasses", NSStringFromSelector(_cmd)];
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:nil];
}

RACSignal

综述

RACEmptySignal/RACReturnSignal/RACErrorSignal/RACDynamicSignal都是对于RACSignal的补充,帮其完善已有的方法

RACEmptySignal

  • 解释:空信号,用来实现RACSignal的 +empty 方法
  • 作用:在一些信号的创建的时候,不能返回nil,需要返回一个空信号
  • 原理:在使用+[RACSignal empty]方法的时候,其内部转到了RACEmptySignal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@implementation RACSignal (RACStream)
+ (RACSignal *)empty {
return [RACEmptySignal empty];
}
@end
@implementation RACEmptySignal
+ (RACSignal *)empty {
return [[[self alloc] init] setNameWithFormat:@"+empty"];
}
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
return [RACScheduler.subscriptionScheduler schedule:^{
[subscriber sendCompleted];
}];
}
@end
  • 使用案例:
    1
    2
    3
    4
    5
    6
    _buttonCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
    @strongify(self);
    RACSignal *signal = ...;
    // 根据条立案来创建信号
    return signal;
    }];

Note: 为了篇幅问题,上面的创建函数方法都被删减过,区别只在于DEBUG和REALSE情况下是够为单例,其他没有问题

RACReturnSignal

  • 解释:一元信号,用来实现 RACSignal 的 +return: 方法;
  • 作用:通常用于信号的转换操作,平常用的不多
  • 原理:在使用+[RACSignal return:]方法的时候,其内部转到了RACReturnSignal

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    + (RACSignal *)return:(id)value {
    RACReturnSignal *signal = [[self alloc] init];
    signal->_value = value;
    return signal;
    }
    - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    return [RACScheduler.subscriptionScheduler schedule:^{
    [subscriber sendNext:self.value];
    [subscriber sendCompleted];
    }];
    }
  • 使用案例:

    1
    2
    3
    4
    5
    6
    7
    @weakify(self);
    [[[self.tf_age rac_textSignal] flattenMap:^RACStream *(id value) {
    return [RACReturnSignal return:[NSString stringWithFormat:@"年龄是:%@",value]];
    }] subscribeNext:^(id x) {
    @strongify(self);
    self.lb_age.text = x;
    }];

RACErrorSignal

  • 解释:一元信号,用来实现 RACSignal 的 +error: 方法;
  • 作用:通常用于订阅过程中发生的错误
  • 原理:在使用+[RACSignal error:]方法的时候,其内部转到了RACErrorSignal

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    + (RACSignal *)error:(NSError *)error {
    RACErrorSignal *signal = [[self alloc] init];
    signal->_error = error;
    return signal;
    }
    // 订阅者直接会收到Error信号
    - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    return [RACScheduler.subscriptionScheduler schedule:^{
    [subscriber sendError:self.error];
    }];
    }
  • 使用案例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    + (RACSignal *)userRegister:(NSString *)loginId
    authCode:(NSString *)authCode
    password:(NSString *)password {
    if (![HZLoginModuleUtils checkPassword:password]) {
    return [RACSignal error:[NSError errorWithDomain:@"HZLoginModule"
    code:1
    userInfo:@{@"message":@"密码格式"}]];
    }
    // balabalabala
    }

RACDynamicSignal

  • 解释:动态信号,使用一个 block 来实现订阅行为,我们在使用 RACSignal 的 +createSignal: 方法时创建的就是该类的实例;
  • 作用:每时每刻用的冷信号都是这么创建的
  • 原理:
    1. 在使用+[RACSignal createSignal:]方法的时候,其内部转到了RACDynamicSignal
    2. RACDynamicSignal copy了一份Block
    3. 在RACDynamicSignal收到订阅的时候,通过RACPassthroughSubscriber包装订阅者和disposable将其进行包装
    4. 包装完成之后,建立Scheduler进行Block执行
    5. 提供dispose方法给外界,可以随时进行信号的销毁。注意这个dispose是复合的dispose不是你自己指定的了。
      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
      + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
      RACDynamicSignal *signal = [[self alloc] init];
      signal->_didSubscribe = [didSubscribe copy];
      return [signal setNameWithFormat:@"+createSignal:"];
      }
      - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
      NSCParameterAssert(subscriber != nil);
      // 这里有一个RACCompoundDisposable,这是一个RACDisposable,只不过RACCompoundDisposable可以存放多个RACDisposable 。当RACCompoundDisposable 执行dispose方法时,它所存放的disposable都会被释放。
      RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
      // 订阅者每一次订阅信号是产生一个 Disposable ,并将其与此次订阅关联起来,通过装饰器 RACPassthroughSubscriber 来做到,装饰器的功能如下:
      // - 包装真正的订阅者,使自己成为订阅者的替代者
      // - 将真正的订阅者与一个订阅时产生的 Disposable 关联起来。
      subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
      if (self.didSubscribe != NULL) {
      // 将当前的运行转接到RACScheduler进行
      RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
      // 调用真正的订阅,但是传递的并非之前的订阅者,而是装饰器
      RACDisposable *innerDisposable = self.didSubscribe(subscriber);
      [disposable addDisposable:innerDisposable];
      }];
      [disposable addDisposable:schedulingDisposable];
      }
      return disposable;
      }

Note:RACDynamicSignal 使用 RACPassthroughSubscriber ,订阅者装饰器直接伪装成真正的订阅器,传给 didSubscribe 这个 block 使用。在这个 block 中,会有一些事件发送给订阅者装饰器,而这个订阅者装饰器则根据 disposable 的状态来来决定是否转发给真正的订阅者。disposable 作为返回值,返回给外部,也就是说能够从外部来取消这个订阅了。

  • 使用案例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    RACSignal *aSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    // 此处subscriber为转换后的subscriber
    [subscriber sendNext:@"abc"];
    [subscriber sendCompleted];
    return [RACDisposable disposableWithBlock:^{
    NSLog(@"disposable");
    }];
    }];

RACChannelTerminal

我们先来看看双向绑定这件事情。
IMAGE
我们如何实现信号从A传到B,又可以从B传到A呢。利用信号的双向传递的话,我们可以用RACSubject,这样A发的信号B就能接到,而且B发的信号A也能够接收到。
IMAGE
这样也有个问题,因为A是Subject的订阅者又是接受者,A发送给B的东西,A也同样会被接受到,这是我们不希望看到的。

  • 解释:为了解决数据双向传递,特别设计的一个类
  • 作用:上面已经有描述不再说了
  • 案例:
    1
    2
    3
    4
    5
    6
    // 建立双向绑定方式1
    RACChannelTo(self,string1) = RACChannelTo(self,string2);
    // 建立双向绑定方式2
    self.channel1 = [[RACKVOChannel alloc] initWithTarget:self keyPath:@"string1" nilValue:nil];
    self.channel2 = [[RACKVOChannel alloc] initWithTarget:self keyPath:@"string2" nilValue:nil];
    self.channel1[@"followingTerminal"] = self.channel2[@"followingTerminal"];

方案2只是方案1的展开,我们平时用的都是RACKVOChannel。所以以此为例

  • 订阅关系
    IMAGE
    特别解释:
  1. lead中的value等于follow的other
    3=7 4=6 10=12 11=13
  2. 同一个Terminal中的信号不会进行互相传递,因为使用ignoreValues进行了忽略(只是提及大可忽略这条规则)
  3. string1和string2并不是真正的订阅者。这边只是为了显示方便给大家演示这么写了。
    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
    @implementation RACChannel
    - (instancetype)init {
    self = [super init];
    RACReplaySubject *leadingSubject = [[RACReplaySubject replaySubjectWithCapacity:0] setNameWithFormat:@"leadingSubject"];
    RACReplaySubject *followingSubject = [[RACReplaySubject replaySubjectWithCapacity:1] setNameWithFormat:@"followingSubject"];
    [[leadingSubject ignoreValues] subscribe:followingSubject];
    [[followingSubject ignoreValues] subscribe:leadingSubject];
    // 结合下面的Terminal初始化,即可看到leaf的value和follow的other是相等的
    _leadingTerminal = [[[RACChannelTerminal alloc] initWithValues:leadingSubject otherTerminal:followingSubject] setNameWithFormat:@"leadingTerminal"];
    _followingTerminal = [[[RACChannelTerminal alloc] initWithValues:followingSubject otherTerminal:leadingSubject] setNameWithFormat:@"followingTerminal"];
    return self;
    }
    @end
    @implementation RACChannelTerminal
    - (instancetype)initWithValues:(RACSignal *)values otherTerminal:(id<RACSubscriber>)otherTerminal {
    NSCParameterAssert(values != nil);
    NSCParameterAssert(otherTerminal != nil);
    self = [super init];
    _values = values;
    _otherTerminal = otherTerminal;
    return self;
    }
    @end
  • 发送流程
  1. String1开始发出了属性改变的信号。
  2. 由1.2.3这个value订阅者进行信号的接收
  3. 由于3=7,3又是热信号,收到信号后进行信号转发发送给13这个订阅者
  4. 由于13=11,11为热信号,收到信号后,发送给订阅者。执行setValue:ForKey:将值进行传递
  • 看下代码
    步骤1中的关键代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 这段是KVC注册属性变化之后的信号回调处理
    RACDisposable *observationDisposable = [strongTarget rac_observeKeyPath:keyPath options:NSKeyValueObservingOptionInitial observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
    if (!causedByDealloc && affectedOnlyLastComponent && self.currentThreadData.ignoreNextUpdate) {
    [self destroyCurrentThreadData];
    return;
    }
    // 交给了leadingTerminal进行信号转发
    [self.leadingTerminal sendNext:value];
    }];

在Terminal中,我们可以看到其实terminal只是作为包装而已,真正发送和订阅时由value和other来进行订阅和发送的。

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
@implementation RACChannelTerminal
#pragma mark Lifecycle
- (instancetype)initWithValues:(RACSignal *)values otherTerminal:(id<RACSubscriber>)otherTerminal {
NSCParameterAssert(values != nil);
NSCParameterAssert(otherTerminal != nil);
self = [super init];
_values = values;
_otherTerminal = otherTerminal;
return self;
}
#pragma mark RACSignal
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
return [self.values subscribe:subscriber];
}
#pragma mark <RACSubscriber>
- (void)sendNext:(id)value {
[self.otherTerminal sendNext:value];
}
- (void)sendError:(NSError *)error {
[self.otherTerminal sendError:error];
}
- (void)sendCompleted {
[self.otherTerminal sendCompleted];
}
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable {
[self.otherTerminal didSubscribeWithDisposable:disposable];
}
@end

步骤4中的关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[[self.leadingTerminal
finally:^{
[observationDisposable dispose];
}]
subscribeNext:^(id x) {
NSObject *object = (keyPathComponentsCount > 1 ? [self.target valueForKeyPath:keyPathByDeletingLastKeyPathComponent] : self.target);
if (object == nil) return;
[self createCurrentThreadData];
self.currentThreadData.ignoreNextUpdate = YES;
// 可以看到收到信号后,进行setValue:forKey:进行赋值
[object setValue:x ?: nilValue forKey:lastKeyPathComponent];
} error:^(NSError *error) {
NSCAssert(NO, @"Received error in %@: %@", self, error);
// Log the error if we're running with assertions disabled.
NSLog(@"Received error in %@: %@", self, error);
}];

热信号

RACSubject

了解RACSubject先扯一扯热冷信号概念
冷信号:冷信号只会在被订阅时,向订阅者发送通知。
热信号:热信号会在任意时间发送出信号,向所有订阅者发送。
举个购买报纸的🌰
冷信号:你每次去杂货铺购买报纸,才会拿到报纸
热信号:你向报社订阅报纸,报社会主动每天早上给你发报纸,不管你要不要接受,都给你发送

区别之处冷信号会直接去发送订阅内容

1
2
3
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
self.didSubscribe(subscriber);
}

而热信号并不会及时发送订阅内容,而是在推送数据的时候,遍历订阅人,进行数据的推送
盗一张图来用一下出处
IMAGE
订阅过程

  1. 初始化一个装饰器
  2. 将订阅者加入当前订阅者数组内
  3. 创建disposable,在订阅者被销毁(指的是被dispose)的同时,将订阅者从订阅列表中进行移除
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
    subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
    NSMutableArray *subscribers = self.subscribers;
    @synchronized (subscribers) {
    [subscribers addObject:subscriber];
    }
    [disposable addDisposable:[RACDisposable disposableWithBlock:^{
    @synchronized (subscribers) {
    NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id<RACSubscriber> obj, NSUInteger index, BOOL *stop) {
    return obj == subscriber;
    }];
    if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
    }
    }]];
    return disposable;
    }

IMAGE
发送消息的过程

  1. 遍历当前订阅者列表中有哪些元素
  2. 向订阅者发送订阅的消息
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    - (void)sendNext:(id)value {
    [self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
    [subscriber sendNext:value];
    }];
    }
    - (void)sendError:(NSError *)error {
    [self.disposable dispose];
    [self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
    [subscriber sendError:error];
    }];
    }
    - (void)sendCompleted {
    [self.disposable dispose];
    [self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
    [subscriber sendCompleted];
    }];
    }

冷信号的使用

1
2
3
4
5
6
7
8
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"😜"];
return nil;
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];

输出

1
HZReactiveCocoaTest_Example[52485:35373322] 😜

热信号的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
RACSubject *subject = [RACSubject subject];
// Subscriber 1
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"1st Sub: %@", x);
}];
[subject sendNext:@1];
// Subscriber 2
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"2nd Sub: %@", x);
}];
[subject sendNext:@2];
// Subscriber 3
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"3rd Sub: %@", x);
}];
[subject sendNext:@3];
[subject sendCompleted];

输出

1
2
3
4
5
6
HZReactiveCocoaTest_Example[52559:35393828] 1st Sub: 1
HZReactiveCocoaTest_Example[52559:35393828] 1st Sub: 2
HZReactiveCocoaTest_Example[52559:35393828] 2nd Sub: 2
HZReactiveCocoaTest_Example[52559:35393828] 1st Sub: 3
HZReactiveCocoaTest_Example[52559:35393828] 2nd Sub: 3
HZReactiveCocoaTest_Example[52559:35393828] 3rd Sub: 3

盗一张图来用一下出处
IMAGE
热信号不会再订阅的时候向订阅人去发送消息,只会在消息发送出去时候,向订阅者发送消息

RACGroupedSignal

  • 解释:分组信号,用来实现 RACSignal 的分组功能;
  • 作用:信号中包含一个key的属性,用来分组
  • 原理:

    1
    2
    3
    4
    5
    + (instancetype)signalWithKey:(id<NSCopying>)key {
    RACGroupedSignal *subject = [self subject];
    subject.key = key;
    return subject;
    }
  • 案例:

    1. 配合groupBy:transform:进行信号的组合
    2. 所有数字大于3的生成一个good为key的RACGroupedSignal,小于3的会生成一个bad的RACGroupedSignal
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber)
      {
      [subscriber sendNext:@1];
      [subscriber sendNext:@2];
      [subscriber sendNext:@3];
      [subscriber sendNext:@4];
      [subscriber sendNext:@5];
      [subscriber sendCompleted];
      return [RACDisposable disposableWithBlock:^{
      NSLog(@"signal dispose");
      }];
      }];
      // 这段代码还无法完全解释,关于filter机制方面还不是很懂,再研究研究
      RACSignal *signalGroup = [signalA groupBy:^id<NSCopying>(NSNumber *object) {
      return object.integerValue > 3 ? @"good" : @"bad";
      } transform:^id(NSNumber * object) {
      return @(object.integerValue * 10);
      }];
      [[[signalGroup filter:^BOOL(RACGroupedSignal *value) {
      return [(NSString *)value.key isEqualToString:@"good"];
      }] flatten]subscribeNext:^(id x) {
      NSLog(@"subscribeNext: %@", x);
      }];

输出

1
2
3
HZReactiveCocoaTest_Example[55955:37029147] subscribeNext: 40
HZReactiveCocoaTest_Example[55955:37029147] subscribeNext: 50
HZReactiveCocoaTest_Example[55955:37029147] signal dispose

RACBehaviorSubject

  • 解释:RACBehaviorSubject是对RACSubject的扩充
  • 作用:在订阅时会向订阅者发送最新的消息,内部会保存一个currentValue即消息的最新值
  • 原理:内部有一个currentValue属性将数据进行保存。每次sendNext的时候就会将其进行发送
  • 注意点:每次订阅的时候,会默认的去发送一次sendNext:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @property (nonatomic, strong) id currentValue;
    - (void)sendNext:(id)value {
    @synchronized (self) {
    self.currentValue = value;
    [super sendNext:value];
    }
    }
    - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    RACDisposable *subscriptionDisposable = [super subscribe:subscriber];
    RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
    @synchronized (self) {
    [subscriber sendNext:self.currentValue];
    }
    }];
    return [RACDisposable disposableWithBlock:^{
    [subscriptionDisposable dispose];
    [schedulingDisposable dispose];
    }];
    }
  • 案例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    RACBehaviorSubject *subject = [RACBehaviorSubject subject];
    [subject subscribeNext:^(id _Nullable x) {
    NSLog(@"1st Sub: %@", x);
    }];
    [subject sendNext:@1];
    [subject subscribeNext:^(id _Nullable x) {
    NSLog(@"2nd Sub: %@", x);
    }];
    [subject sendNext:@2];
    [subject subscribeNext:^(id _Nullable x) {
    NSLog(@"3rd Sub: %@", x);
    }];
    [subject sendNext:@3];
    [subject sendCompleted];

嗯,又要盗图了
IMAGE
因为默认会发送一次,所以创建的时候允许创建默认值

1
RACBehaviorSubject *subject = [RACBehaviorSubject behaviorSubjectWithDefaultValue:@0];

RACReplaySubject

  • 解释:RACReplaySubject则是对RACBehaviorSubject的再一次加强,是保存所有值,而不仅仅是保存最新值
  • 作用:在订阅时会向订阅者发送热信号创建以来发送过的所有数据
  • 原理:内部包含有消息数组,默认存储量是无符号整型的最大值
    发送过程
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    - (void)sendNext:(id)value {
    @synchronized (self) {
    [self.valuesReceived addObject:value ?: RACTupleNil.tupleNil];
    [super sendNext:value];
    if (self.capacity != RACReplaySubjectUnlimitedCapacity && self.valuesReceived.count > self.capacity) {
    [self.valuesReceived removeObjectsInRange:NSMakeRange(0, self.valuesReceived.count - self.capacity)];
    }
    }
    }

订阅过程

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
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable];
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
@synchronized (self) {
for (id value in self.valuesReceived) {
if (compoundDisposable.disposed) return;
[subscriber sendNext:(value == RACTupleNil.tupleNil ? nil : value)];
}
if (compoundDisposable.disposed) return;
if (self.hasCompleted) {
[subscriber sendCompleted];
} else if (self.hasError) {
[subscriber sendError:self.error];
} else {
RACDisposable *subscriptionDisposable = [super subscribe:subscriber];
[compoundDisposable addDisposable:subscriptionDisposable];
}
}
}];
[compoundDisposable addDisposable:schedulingDisposable];
return compoundDisposable;
}

  • 注意点:当然你也可以设置存储历史消息的数量,跟behavior一样,已创建就会发送历史消息

    1
    2
    3
    + (instancetype)replaySubjectWithCapacity:(NSUInteger)capacity {
    return [(RACReplaySubject *)[self alloc] initWithCapacity:capacity];
    }
  • 使用案例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    RACReplaySubject *subject = [RACReplaySubject subject];
    [subject subscribeNext:^(id _Nullable x) {
    NSLog(@"1st Subscriber: %@", x);
    }];
    [subject sendNext:@1];
    [subject subscribeNext:^(id _Nullable x) {
    NSLog(@"2nd Subscriber: %@", x);
    }];
    [subject sendNext:@2];
    [subject subscribeNext:^(id _Nullable x) {
    NSLog(@"3rd Subscriber: %@", x);
    }];
    [subject sendNext:@3];
    [subject sendCompleted];

0 0请允许我再盗一次图
IMAGE

参考链接

ReactiveCocoa信号发送详解
RAC 中的双向数据绑定
RACSubject
RACGroupedSignal