簡介
ReactiveCocoa是一個基于函數響應式編程思想(Funcation Reactive Programming,簡稱FRP)的框架。由幾個重要的部分組成,如下:
信號:例如RACSignal,他可以被訂閱,訂閱后進行邏輯處理或者數據傳遞。
訂閱者:例如RACSubscriber,表示訂閱者的意思。用于訂閱和發送數據。它是一個協議,由具體的類實現。
清理者:例如RACDisposable,用于取消或者清理訂閱者的資源。
RACSubject:可以當成一個信號,也可以充當信號發送者。
一個簡單的流程分析
最基本的流程可以是,創建一個信號,然后創建一個訂閱者并且訂閱這個信號。
//首先創建一個信號
RACSignal *signal = [RACSignal create:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"test"]; //被subscriber訂閱后,觸發subscriber的sendNext方法,傳遞數據
}];
[signal subscribeNext:^(id x) {
NSLog(x); //將傳遞的數據數據輸出
}];
//輸出"test"
//創建一個RACDynamicSignal信號,指定了被訂閱后的回調邏輯
+ (RACSignal *)create:(void (^)(id<RACSubscriber>))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+create:"];
}
//創界一個訂閱者,并且訂閱信號
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock {
RACLiveSubscriber *subscriber = [RACLiveSubscriber subscriberWithNext:nextBlock error:errorBlock completed:completedBlock];
subscriber.signal = self; //subscriber關聯信號
[self attachSubscriber:subscriber]; //信號被subscriber訂閱
return subscriber.disposable;
}
1.create:方法創建一個RACDynamicSignal類型的信號signal,并且指定了被訂閱后的回調邏輯。
2.創建一個RACLiveSubscriber類型的訂閱者subscriber,subscriber分別維護了3個block,用于處理next事件,error事件和completed事件的數據,本例的error和completed回調均為nil。
3.subscriber訂閱signal,RACDynamicSignal類型的信號在attachSubscriber方法中會觸發_didSubscribe回調,并傳入subscriber。在回調邏輯里,subscriber觸發next事件,傳遞數據。
4.subscriber的next回調接收到數據后,輸出。
訂閱方法
RACSignal信號類提供了一系列訂閱信號的方法,但都是基于上文的subscribeNext:error:completed:,例如:
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
return [self subscribeNext:nextBlock error:nil completed:nil];
}
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock completed:(void (^)(void))completedBlock {
return [self subscribeNext:nextBlock error:nil completed:completedBlock];
}
- (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock {
return [self subscribeNext:nil error:errorBlock completed:nil];
}
- (RACDisposable *)subscribeCompleted:(void (^)(void))completedBlock {
return [self subscribeNext:nil error:nil completed:completedBlock];
}
還有一個較為不同的方法是:
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
RACLiveSubscriber *liveSubscriber;
if (subscriber == nil) {
//創建一個RACLiveSubscriber,維護三個block,即next、error和completed,但只都是nil
liveSubscriber = [RACLiveSubscriber subscriberWithNext:nil error:nil completed:nil];
} else {
//創建一個RACLiveSubscriber,維護三個block,即next、error和completed
liveSubscriber = [RACLiveSubscriber subscriberForwardingToSubscriber:subscriber];
}
liveSubscriber.signal = self;
[self attachSubscriber:liveSubscriber];
return liveSubscriber.disposable;
}
該方法根據一個已有的subscriber,套一個新的RACLiveSubscriber類型的liveSubscriber在外面,liveSubscriber內部的next、error和completed回調會觸發原subscriber的對應回調。
+ (instancetype)subscriberForwardingToSubscriber:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
//新liveSubscriber的三個block分別去調用原subscriber的三個block
RACLiveSubscriber *liveSubscriber = [self subscriberWithNext:^(id x) {
[subscriber sendNext:x];
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
[subscriber sendCompleted];
}];
[subscriber.disposable addDisposable:liveSubscriber.disposable];
[liveSubscriber.disposable addDisposable:[RACDisposable disposableWithBlock:^{
[subscriber.disposable removeDisposable:liveSubscriber.disposable];
}]];
return liveSubscriber;
}
將新liveSubscriber的disposable加入原subscriber的disposable隊列中,關聯兩者的disposable對象。
RACDisposable
RACDisposable相關類負責清理訂閱者的資源,例如創建一個RACDisposable的方法:
RACDisposable *disposable = [RACDisposable disposableWithBlock:^{
//...執行相關邏輯
}];
disposable對象里面維護一個block,當執行dispose方法時,會執行block。RACCompoundDisposable對象是RACDisposable對象的子類,作用是維護一個隊列,里面存放了若干個disposable對象,RACCompoundDisposable對象執行dispose方法時,將隊列中的disposable對象依次執行dispose方法。
和訂閱者結合使用情況下,每個訂閱者會維護一個RACCompoundDisposable對象disposable,如下:
@protocol RACSubscriber <NSObject>
@required
@property (nonatomic, strong, readonly) RACCompoundDisposable *disposable;
- (void)sendNext:(id)value;
- (void)sendError:(NSError *)error;
- (void)sendCompleted;
@end
除了實現三個事件觸發的方法,還有一個RACCompoundDisposable對象disposable,以RACLiveSubscriber為例,在初始化的時候會創建一個RACCompoundDisposable對象,如下:
- (id)init {
...
//創建一個selfDisposable對象,用于將三個事件block置為nil
RACDisposable *selfDisposable = [RACDisposable disposableWithBlock:^{
@strongify(self);
if (self == nil) return;
OSSpinLockLock(&self->_spinLock);
self.next = nil;
self.error = nil;
self.completed = nil;
OSSpinLockUnlock(&self->_spinLock);
}];
//將selfDisposable對象加入隊列對象中
_disposable = [RACCompoundDisposable compoundDisposableWithDisposables:@[ selfDisposable ]];
return self;
}
接著分析上面的subscriberForwardingToSubscriber:方法
[subscriber.disposable addDisposable:liveSubscriber.disposable];
[liveSubscriber.disposable addDisposable:[RACDisposable disposableWithBlock:^{
[subscriber.disposable removeDisposable:liveSubscriber.disposable];
}]];
將新的liveSubscriber對象的disposable對象加入原subscriber對象的disposable隊列中。之所以這樣做,我的理解是liveSubscriber基于subscriber創建,因此當subscriber在某種情況dispose,相關聯的liveSubscriber失去存在意義,也要dispose,將其三個事件的block置為nil,同時將liveSubscriber的disposable對象從隊列中移除。
attachSubscriber:
attachSubscriber:負責signal被訂閱后的邏輯,基類RACSignal默認不實現任何功能,如下:
- (void)attachSubscriber:(RACLiveSubscriber *)subscriber {
NSCAssert(NO, @"This method must be overridden by subclasses.");
}
不同的signal子類實現邏輯不一樣,以create:方法創建的RACDynamicSignal類為例,如下:
- (void)attachSubscriber:(RACLiveSubscriber *)subscriber {
NSCParameterAssert(subscriber != nil);
if (self.didSubscribe != NULL) { //執行signal的_didSubscribe回調
self.didSubscribe(subscriber);
}
}
以RACReturnSignal類為例,如下:
- (void)attachSubscriber:(RACLiveSubscriber *)subscriber {
NSCParameterAssert(subscriber != nil);
[subscriber sendNext:self.value]; //觸發subscriber的next事件,將value作為數據傳遞
[subscriber sendCompleted]; //觸發subscriber的comple事件
}
總結
RAC框架通過block回調的方式實現FRP編程思想,每一次操作會觸發一個對應的block作為響應,傳遞數據,在寫法上使代碼高聚合,方便管理。