ReactiveCocoa 使用.RACSubject类使用
2017-08-31 本文已影响0人
土豆萝卜君
我们知道只要创建一个信号,在有一个订阅者去订阅她我们就可以发送消息了。但是有没有一个对象既可以发送消息又可以订阅消息呢? 这时候RACSubject 就出现了,因为它继承与RACSignal信号类又遵守RACSubscribe协议这样达到了就既能发送,又能订阅信号的操作了。他的使用场景可以做为代理来使用 或者 用来绑定ViewModel和View
RACSubject
- (void)subjectTest {
RACSubject *subject = [RACSubject subject];
// 2.订阅信号(这里可以创建多个订阅者)
[subject subscribeNext:^(id x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第一个订阅者%@",x);
}];
[subject subscribeNext:^(id x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第二个订阅者%@",x);
}];
[subject subscribeNext:^(id x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第三个订阅者%@",x);
}];
// 3.发送信号
[subject sendNext:@"1"];
}
RACReplaySubject
- 可以先订阅信号,也可以先发送信号
- 调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
- 调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock
如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。
- (void)replaySubjectTest{
RACReplaySubject *replaySubject = [RACReplaySubject subject];
// 2.发送信号
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
// 3.订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一个订阅者接收到的数据%@",x);
}];
// 订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二个订阅者接收到的数据%@",x);
}];
}
上一篇讲解了下RACSignal内部的流程,知道了RACSignal在看RACSubject就简单很多了,毕竟是RACSubject继承与RACSignal,一些方法都是大同小异的。
1 创建信号
+ (instancetype)subject {
return [[self alloc] init];
}
- (id)init {
self = [super init];
if (self == nil) return nil;
_disposable = [RACCompoundDisposable compoundDisposable];
_subscribers = [[NSMutableArray alloc] initWithCapacity:1];
return self;
}
- 创建RACSubject对象的时候同时创建了相应的一个disposable和一个订阅者数组,仅仅而已
2 订阅信号
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
NSMutableArray *subscribers = self.subscribers;
@synchronized (subscribers) {
[subscribers addObject:subscriber];
}
return [RACDisposable disposableWithBlock:^{
@synchronized (subscribers) {
// Since newer subscribers are generally shorter-lived, search
// starting from the end of the list.
NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id<RACSubscriber> obj, NSUInteger index, BOOL *stop) {
return obj == subscriber;
}];
if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
}
}];
}
- RACSubejct是可以多次订阅的 它把生产的订阅者存入订阅者数组中,每个订阅者都包含自己的对应的block(next,error,complete)
- 它比RACSignal取消的时候多做了一些清理工作,把订阅者数组中的相对于的订阅者去除并取消
3 发送信号
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:value];
}];
}
- 先遍历订阅者数组中的订阅者
- 后执行订阅者中的nextBlock
- 订阅者发送信号
借用他们的流程图为
1467716-f2b4f5f91210d0ba.png