RACSubject 信号提供者!!,自己可以充当信号,又能够发送信号!!
首先回顾一下
RACDisposable:它可以帮助我们取消订阅.信号发送完毕了 ,失败了.
RACSubscriber(协议):订阅者(发送信号!)
RACSubject :信号提供者!!,自己可以充当信号,又能够发送信号!!
RACSubject:这个类叫做信号提供者,自己可以充当信号,又能够发送信号!!
@interface RACSubject<ValueType> : RACSignal<ValueType> <RACSubscriber>
编程思想:《面向协议的开发》
OC里边没有多继承这一说,那么我(RACSubject)想继承另一个类(RACSignal)里的功能:
就需要 我(RACSubject) 遵守 订阅者协议< RACSubscriber >,实现订阅者协议的方法,就可以了。
就是面向协议的开发的应用场景。
还是三步走:
1.创建信号
2.订阅信号
3.发送数据
//1.创建信号
RACSubject *subject = [RACSubject subject];
//2.订阅信号
//不同的信号订阅的方式不一样!!因为类型不一样,所以调用的方法不一样。
//RACSubject处理订阅 :拿到之前的_subscribers 保存订阅者
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"接收到的数据 x 是 %@",x);
}];
//3.发送数据
//遍历出所有的订阅者,其实还是调用的nextBlock
[subject sendNext:@"数据A"];
打印的结果:
2017-06-15 16:18:54.468 RAC-demo[41104:6465743] 接收到的数据 x 是 数据A
多订阅者
//1.创建信号
RACSubject *subject = [RACSubject subject];
//2.订阅信号
//不同的信号订阅的方式不一样!!因为类型不一样,所以调用的方法不一样。
//RACSubject处理订阅 :拿到之前的_subscribers 保存订阅者
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"订阅1⃣️ 接收到的数据 x 是 %@",x);
}];
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"订阅2⃣️ 接收到的数据 x 是 %@",x);
}];
//3.发送数据
//遍历出所有的订阅者,其实还是调用的nextBlock
[subject sendNext:@"数据A"];
打印的结果:
2017-06-15 17:04:56.804 RAC-demo[41379:6621767] 订阅1⃣️ 接收到的数据 x 是 数据A
2017-06-15 17:04:56.805 RAC-demo[41379:6621767] 订阅2⃣️ 接收到的数据 x 是 数据A
实现原理
1、创建信号
订阅管理者(_disposable)、保存订阅者的数组(_subscribers)
" cmd "点"subject"进去
" [RACSubject subject] "
// This should only be used while synchronized on `self`.
@property (nonatomic, strong, readonly) NSMutableArray *subscribers;
// Contains all of the receiver's subscriptions to other signals.
@property (nonatomic, strong, readonly) RACCompoundDisposable *disposable;
+ (instancetype)subject {
return [[self alloc] init];
}
- (instancetype)init {
self = [super init];
if (self == nil) return nil;
_disposable = [RACCompoundDisposable compoundDisposable];
_subscribers = [[NSMutableArray alloc] initWithCapacity:1];
return self;
}
- (void)dealloc {
[self.disposable dispose];
}
作者在重写的init方法里面进行了创建信号订阅管理者(_disposable)、保存订阅者的数组(_subscribers),
便于多个订阅者订阅
"_disposable"、"_subscribers"
2、订阅信号
RACSubject处理订阅 :拿到之前的_subscribers 保存订阅者
"cmd"点"subscribeNext "进去
" [subject subscribeNext:^(id _Nullable x) {}] "
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
保存Block
nextBlock
注意" [self subscribe:o] "
"cmd"点"subscribe "进去
此处的"self"代表的是"RACSubject"
- (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];
}
[disposable addDisposable:[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];
}
}]];
return disposable;
}
保存所有订阅者
[subscribers addObject:subscriber];
#@synchronized上锁的原因是:@synchronized() 的作用是:
#创建一个互斥锁,保证在同一时间内没有其它线程对self对象进行修改,起到线程的保护作用,
#一般在公用变量的时候使用,如单例模式或者操作类的static变量中使用。
这里把订阅管理者disposable返回出去便于 手动 取消订阅
3、发送数据
遍历出所有的订阅者,其实还是调用的nextBlock
"cmd"点"sendNext"进去
"[subject sendNext:@"数据A"]"
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:value];
}];
}
看到"enumerateSubscribersUsingBlock"就知道这是个循环,
就是要把之前保存的订阅者一个一个找出发送信号
#下边这个方法证实了这个的想法:
- (void)enumerateSubscribersUsingBlock:(void (^)(id<RACSubscriber> subscriber))block {
NSArray *subscribers;
@synchronized (self.subscribers) {
subscribers = [self.subscribers copy];
}
for (id<RACSubscriber> subscriber in subscribers) {
block(subscriber);
}
}
#block(subscriber);
block一调用就近到了"[subscriber sendNext:value];"方法
#pragma mark RACSubscriber
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
#看到了熟悉的
nextBlock(value);
这就表示在这里进行了发送数据把保存的nextBlock一执行就实现了数据返回后的处理了。
流程图示: