我們知道只要創(chuàng)建一個信號,在有一個訂閱者去訂閱她我們就可以發(fā)送消息了。但是有沒有一個對象既可以發(fā)送消息又可以訂閱消息呢喜庞? 這時候RACSubject 就出現(xiàn)了案狠,因為它繼承與RACSignal信號類又遵守RACSubscribe協(xié)議這樣達(dá)到了就既能發(fā)送,又能訂閱信號的操作了卷雕。他的使用場景可以做為代理來使用 或者 用來綁定ViewModel和View
RACSubject
- (void)subjectTest {
RACSubject *subject = [RACSubject subject];
// 2.訂閱信號(這里可以創(chuàng)建多個訂閱者)
[subject subscribeNext:^(id x) {
// block調(diào)用時刻:當(dāng)信號發(fā)出新值节猿,就會調(diào)用.
NSLog(@"第一個訂閱者%@",x);
}];
[subject subscribeNext:^(id x) {
// block調(diào)用時刻:當(dāng)信號發(fā)出新值,就會調(diào)用.
NSLog(@"第二個訂閱者%@",x);
}];
[subject subscribeNext:^(id x) {
// block調(diào)用時刻:當(dāng)信號發(fā)出新值,就會調(diào)用.
NSLog(@"第三個訂閱者%@",x);
}];
// 3.發(fā)送信號
[subject sendNext:@"1"];
}
RACReplaySubject
- 可以先訂閱信號滨嘱,也可以先發(fā)送信號
- 調(diào)用sendNext發(fā)送信號峰鄙,把值保存起來,然后遍歷剛剛保存的所有訂閱者太雨,一個一個調(diào)用訂閱者的nextBlock吟榴。
- 調(diào)用subscribeNext訂閱信號,遍歷保存的所有值囊扳,一個一個調(diào)用訂閱者的nextBlock
如果想當(dāng)一個信號被訂閱吩翻,就重復(fù)播放之前所有值,需要先發(fā)送信號宪拥,在訂閱信號仿野。
- (void)replaySubjectTest{
RACReplaySubject *replaySubject = [RACReplaySubject subject];
// 2.發(fā)送信號
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
// 3.訂閱信號
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一個訂閱者接收到的數(shù)據(jù)%@",x);
}];
// 訂閱信號
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二個訂閱者接收到的數(shù)據(jù)%@",x);
}];
}
上一篇講解了下RACSignal內(nèi)部的流程,知道了RACSignal在看RACSubject就簡單很多了她君,畢竟是RACSubject繼承與RACSignal脚作,一些方法都是大同小異的。
1 創(chuàng)建信號
+ (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;
}
- 創(chuàng)建RACSubject對象的時候同時創(chuàng)建了相應(yīng)的一個disposable和一個訂閱者數(shù)組,僅僅而已
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是可以多次訂閱的 它把生產(chǎn)的訂閱者存入訂閱者數(shù)組中缔刹,每個訂閱者都包含自己的對應(yīng)的block(next,error,complete)
- 它比RACSignal取消的時候多做了一些清理工作球涛,把訂閱者數(shù)組中的相對于的訂閱者去除并取消
3 發(fā)送信號
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:value];
}];
}
- 先遍歷訂閱者數(shù)組中的訂閱者
- 后執(zhí)行訂閱者中的nextBlock
- 訂閱者發(fā)送信號
借用他們的流程圖為
1467716-f2b4f5f91210d0ba.png