When subclassing RACStream, only the methods in the main @interface body need to be overridden.
以上是RACStream類的簡要介紹中的一段話,大意為只有主類中聲明的方法需要在子類重寫。查看類實(shí)現(xiàn)文件發(fā)現(xiàn)主類中聲明的方法全部都很厚道的 return nil 液走,因此我們在介紹以下方法時會使用其子類RACSignal做演示精拟。
+ (instancetype)empty;
empty函數(shù)返回一個名為 +empty 的stream,這個stream會被立即結(jié)束裙戏,不做任何操作。
+ (instancetype)return:(id)value;
創(chuàng)建一個名為 +return: value 的stream,這個stream返回給定值后結(jié)束瘤旨。
//value:值 stop:如果設(shè)置為YES則終止后續(xù)值
typedef RACStream * (^RACStreamBindBlock)(id value, BOOL *stop);
- (instancetype)bind:(RACStreamBindBlock (^)(void))block;
原始 stream 每產(chǎn)生一個 value 將 value 傳入 RACStreamBindBlock 產(chǎn)生一個新的 stream 并訂閱這個 stream 。 當(dāng) stop 被設(shè)置為 YES 時終止后續(xù)值發(fā)送竖伯。一旦任意一個由 RACStreamBindBlock 產(chǎn)生的 stream sendError 則原始 stream sendError存哲,當(dāng)所有由 RACStreamBindBlock 產(chǎn)生的 stream sendComplete 則原始 stream sendComplete。
例:
創(chuàng)建一個signal對象發(fā)送十次值七婴,并且在其中隨機(jī)發(fā)送@" "祟偷。我們要做的是過濾掉@" "并且在接收到@"5"時終止后續(xù)發(fā)送返回一個新的signal并且發(fā)送@"a",@"b"打厘。
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//發(fā)送10次值
for (int i = 0; i < 10; i ++) {
//隨機(jī)發(fā)送 @" "
BOOL empty = arc4random_uniform(2);
if (!empty || i == 5) {
[subscriber sendNext:[NSString stringWithFormat:@"%zd",i]];
}
else {
[subscriber sendNext:@" "];
}
}
[subscriber sendCompleted];
return nil;
}] bind:^RACStreamBindBlock{
return ^id (NSString * value, BOOL * stop) {
if ([value isEqualToString:@" "]) { //過濾@" "
return [RACSignal empty];
}
else if ([value isEqualToString:@"5"]){ //接收到 @"5" 終止
* stop = YES;
RACSignal * result = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"a"];
[subscriber sendNext:@"b"];
[subscriber sendCompleted];
return nil;
}];
return result;
}
else {
return [RACSignal return:value];
}
};
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[signal subscribeCompleted:^{
NSLog(@"complete");
}];
/* 某次執(zhí)行結(jié)果
2018-03-27 15:14:02.334078+0800 ReactCocoaTest[91664:2403921] 1
2018-03-27 15:14:02.334390+0800 ReactCocoaTest[91664:2403921] 3
2018-03-27 15:14:02.334562+0800 ReactCocoaTest[91664:2403921] 4
2018-03-27 15:14:02.334836+0800 ReactCocoaTest[91664:2403921] a
2018-03-27 15:14:02.334957+0800 ReactCocoaTest[91664:2403921] b
2018-03-27 15:14:02.335673+0800 ReactCocoaTest[91664:2403921] complete
*/
- (instancetype)concat:(RACStream *)stream;
將 stream a與 stream b 聯(lián)結(jié)起來并產(chǎn)生一個新的 stream c修肠,只有當(dāng)前stream a sendComplete 之后 stream b 才能發(fā)送值,當(dāng) stream a 和 stream b 都 sendComplete 之后户盯,聯(lián)結(jié)產(chǎn)生的stream c 才會 sendComplete嵌施。
注意:如果聯(lián)結(jié)的兩個stream中某個stream sendError 則聯(lián)結(jié)產(chǎn)生的stream立即 sendError 。
例:
創(chuàng)建兩個stream先舷,并且各自延遲5秒 sendComplete
RACSignal * signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[[RACScheduler mainThreadScheduler]afterDelay:5 schedule:^{
[subscriber sendCompleted];
}];
return nil;
}];
RACSignal * signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[[RACScheduler mainThreadScheduler]afterDelay:5 schedule:^{
[subscriber sendCompleted];
}];
return nil;
}];
RACSignal * concat = [signal1 concat:signal2];
[concat subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[concat subscribeCompleted:^{
NSLog(@"complete");
}];
[concat subscribeError:^(NSError *error) {
NSLog(@"error");
}];
/*
2018-03-27 16:37:18.546755+0800 ReactCocoaTest[94470:2467226] 1
2018-03-27 16:37:24.040041+0800 ReactCocoaTest[94470:2467226] 2
2018-03-27 16:37:29.513247+0800 ReactCocoaTest[94470:2467226] complete
*/
可以看到控制臺三次輸出間隔時間為5秒艰管,大家可以將signal1 或者signal2中任意一個 sendComplete 修改為 sendError 驗(yàn)證signal sendError的情況。
//- (instancetype)concat:(RACStream *)stream 的升級版 針對多個stream的情況
+ (instancetype)concat:(id<NSFastEnumeration>)streams;
- (instancetype)zipWith:(RACStream *)stream;
將 stream a 與 stream b 結(jié)合起來產(chǎn)生一個新的 stream c蒋川,當(dāng) stream a 和 stream b 都發(fā)送過一次值之后 stream c 才會將這兩個值通過RACTuple對象發(fā)送牲芋。
注意:
1.stream c 發(fā)送的 RACTuple 中的值為 stream a 與 stream b 同次發(fā)送的值。
2.stream a 與 stream b 中任意一個 sendComplete 則 stream c sendComplete捺球,當(dāng) stream a 與 stream b 任意一個 sendError 則 stream c sendError缸浦。
例:
RACSignal * signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendNext:@"6"];
[[RACScheduler mainThreadScheduler]afterDelay:7 schedule:^{
[subscriber sendError:nil];
}];
return nil;
}];
RACSignal * signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"a"];
[subscriber sendNext:@"b"];
[[RACScheduler mainThreadScheduler]afterDelay:5 schedule:^{
[subscriber sendNext:@"d"];
[subscriber sendCompleted];
}];
return nil;
}];
RACSignal * zip = [signal1 zipWith:signal2];
[zip subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[zip subscribeCompleted:^{
NSLog(@"complete");
}];
[zip subscribeError:^(NSError *error) {
NSLog(@"error");
}];
/*
2018-03-27 17:20:15.922457+0800 ReactCocoaTest[96661:2499724] <RACTuple: 0x604000206030> (
1,
a
)
2018-03-27 17:20:15.922787+0800 ReactCocoaTest[96661:2499724] <RACTuple: 0x604000206010> (
2,
b
)
2018-03-27 17:20:21.414965+0800 ReactCocoaTest[96661:2499724] <RACTuple: 0x604000207110> (
3,
d
)
2018-03-27 17:20:21.415268+0800 ReactCocoaTest[96661:2499724] complete
*/
//- (instancetype)zipWith:(RACStream *)stream 的升級版 針對多個stream的情況
+ (instancetype)zip:(id<NSFastEnumeration>)streams;
- (instancetype)flattenMap:(RACStream * (^)(id value))block;
產(chǎn)生一個新的stream 每當(dāng)stream發(fā)送一個值時會先詢問block并且訂閱block中返回的stream。
flattenMap 適用于stream中嵌套stream的場景氮兵,例如當(dāng)用戶點(diǎn)擊登錄按鈕后我們需要將用戶名密碼等發(fā)送至服務(wù)器效驗(yàn)裂逐,由服務(wù)器返回效驗(yàn)結(jié)果以判斷用戶名密碼等是否正確。
RACSignal * loginSignal = [self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside];
RACSignal * checkUserSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 延時模擬請求
[[RACScheduler mainThreadScheduler]afterDelay:3 schedule:^{
[subscriber sendNext:@"success"];
[subscriber sendCompleted];
}];
return nil;
}];
RACSignal * loginResultSignal = [loginSignal flattenMap:^RACStream *(id value) {
return checkUserSignal;
}];
[loginResultSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
- (instancetype)map:(id (^)(id value))block;
每當(dāng)stream發(fā)送一個value時會將value傳入block產(chǎn)生一個新的value并發(fā)送泣栈。
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@" "];
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return nil;
}] map:^id(NSString * value) {
if ([value isEqualToString:@" "]) {
return @"0";
}
return value;
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
- (instancetype)mapReplace:(id)object;
將 stream 發(fā)送的值全部替換為為object
- (instancetype)filter:(BOOL (^)(id value))block;
stream 每產(chǎn)生一個值都傳入block進(jìn)行測試卜高,當(dāng)block返回NO時該值將不會被訂閱者接收到弥姻。
- (instancetype)ignore:(id)innerValue;
stream 每產(chǎn)生一個value進(jìn)行 value != innerValue && [value -isEqual:innerValue] 運(yùn)算,運(yùn)算結(jié)果為YES時訂閱者不會接收到value掺涛。innerValue 可以被設(shè)置為 nil 庭敦。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:nil];
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return nil;
}]ignore:nil];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
/*
2018-03-28 17:39:59.041 ReactCocoaTest[3000:1590755] 1
2018-03-28 17:39:59.041 ReactCocoaTest[3000:1590755] 1
*/
- (instancetype)reduceEach:(id (^)())reduceBlock;
將stream發(fā)送的RACTuple中的值使用reduceBlock處理為一個值。在方法聲明中并沒有說明reduceBlock的參數(shù)個數(shù)薪缆,使用時注意reduceBlock的參數(shù)個數(shù)要與RACTuple中包含的值的個數(shù)相同秧廉。
例
RACSignal * signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"11"];
[subscriber sendCompleted];
return nil;
}];
RACSignal * signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendNext:@"22"];
[subscriber sendCompleted];
return nil;
}];
RACSignal * signal3 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"3"];
[[RACScheduler mainThreadScheduler]afterDelay:2 schedule:^{
[subscriber sendNext:@"33"];
[subscriber sendCompleted];
}];
return nil;
}];
[[[RACSignal zip:@[signal1,signal2,signal3]] reduceEach:^id(NSString * a, NSString * b, NSString * c){
return [NSString stringWithFormat:@"%@ %@ %@",a,b,c];
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
+ (instancetype)zip:(id<NSFastEnumeration>)streams reduce:(id (^)())reduceBlock;
+zip: 與 -reduceEach:的組合。
- (instancetype)startWith:(id)value;
指定stream的起始值拣帽,當(dāng)訂閱者訂閱stream時會立即收到value所指定的值疼电。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[RACScheduler mainThreadScheduler]afterDelay:2 schedule:^{
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
}];
return nil;
}] startWith:@"0"];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 11:39:17.538975+0800 ReactiveCocoaTest[31885:730340] 0
2018-04-12 11:39:19.540758+0800 ReactiveCocoaTest[31885:730340] 1
- (instancetype)skip:(NSUInteger)skipCount;
跳過指定次數(shù)的值,訂閱者只能接收到第skipCount次之后的值减拭。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[RACScheduler mainThreadScheduler]afterDelay:2 schedule:^{
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
}];
return nil;
}] skip:3];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 15:26:04.206220+0800 ReactiveCocoaTest[36205:852172] 4
2018-04-12 15:26:04.206473+0800 ReactiveCocoaTest[36205:852172] 5
- (instancetype)take:(NSUInteger)count;
只發(fā)送前count次的值蔽豺。
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[RACScheduler mainThreadScheduler]afterDelay:2 schedule:^{
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
}];
return nil;
}] take:3];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 15:27:04.557102+0800 ReactiveCocoaTest[36338:854896] 1
2018-04-12 15:27:04.557391+0800 ReactiveCocoaTest[36338:854896] 2
2018-04-12 15:27:04.557603+0800 ReactiveCocoaTest[36338:854896] 3
- (instancetype)scanWithStart:(id)startingValue reduce:(id (^)(id running, id next))block;
startingValue:block中running的起始值。
block:依次將stream中發(fā)送的值作為next傳入block并且將上一次block的返回值作為running傳入block峡谊。每一次block返回一個值后會將原來的值替換茫虽。
官方給出的例子
RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence;
// Contains 1, 3, 6, 10
RACSequence *sums = [numbers scanWithStart:@0 reduce:^(NSNumber *sum, NSNumber *next) {
return @(sum.integerValue + next.integerValue);
}];
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[RACScheduler mainThreadScheduler]afterDelay:2 schedule:^{
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
}];
return nil;
}] scanWithStart:@"a" reduce:^id(id running, id next) {
return [NSString stringWithFormat:@"%@,%@",running,next];
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 16:35:38.272950+0800 ReactiveCocoaTest[38313:919048] a,1
2018-04-12 16:35:38.273245+0800 ReactiveCocoaTest[38313:919048] a,1,2
2018-04-12 16:35:38.273708+0800 ReactiveCocoaTest[38313:919048] a,1,2,3
2018-04-12 16:35:38.274369+0800 ReactiveCocoaTest[38313:919048] a,1,2,3,4
2018-04-12 16:35:38.274632+0800 ReactiveCocoaTest[38313:919048] a,1,2,3,4,5
- (instancetype)combinePreviousWithStart:(id)start reduce:(id (^)(id previous, id current))reduceBlock;
start:reduceBlock中previous的起始值刊苍。
reduceBlock:依次將stream中上一次發(fā)送的值與當(dāng)前發(fā)送的值分別作為previous和current傳入reduceBlock既们,并得到一個新的值。每一次reduceBlock返回一個值后會將原來的值替換正什。
官方給出的例子
RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence;
// Contains 1, 3, 5, 7
RACSequence *sums = [numbers combinePreviousWithStart:@0 reduce:^(NSNumber *previous, NSNumber *next) {
return @(previous.integerValue + next.integerValue);
}];
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[RACScheduler mainThreadScheduler]afterDelay:2 schedule:^{
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
}];
return nil;
}] combinePreviousWithStart:@"a" reduce:^id(id previous, id current) {
return [NSString stringWithFormat:@"%@,%@",previous,current];
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 16:41:54.005897+0800 ReactiveCocoaTest[38662:929686] a,1
2018-04-12 16:41:54.006375+0800 ReactiveCocoaTest[38662:929686] 1,2
2018-04-12 16:41:54.006617+0800 ReactiveCocoaTest[38662:929686] 2,3
2018-04-12 16:41:54.006957+0800 ReactiveCocoaTest[38662:929686] 3,4
2018-04-12 16:41:54.008215+0800 ReactiveCocoaTest[38662:929686] 4,5
- (instancetype)takeUntilBlock:(BOOL (^)(id x))predicate;
每當(dāng)stream產(chǎn)生一個值都會詢問predicate啥纸,當(dāng)predicate返回YES當(dāng)前值以及后續(xù)值不會被訂閱者接收到。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
return nil;
}] takeUntilBlock:^BOOL(id x) {
return [x isEqualToString:@"3"];
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 16:54:04.421888+0800 ReactiveCocoaTest[39002:945018] 1
2018-04-12 16:54:04.422144+0800 ReactiveCocoaTest[39002:945018] 2
- (instancetype)takeWhileBlock:(BOOL (^)(id x))predicate;
每當(dāng)stream產(chǎn)生一個值都會詢問predicate婴氮,當(dāng)predicate返回NO當(dāng)前值以及后續(xù)值不會被訂閱者接收到斯棒。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
return nil;
}] takeWhileBlock:^BOOL(id x) {
return [x isEqualToString:@"1"];
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 16:57:01.353910+0800 ReactiveCocoaTest[39611:952168] 1
- (instancetype)skipUntilBlock:(BOOL (^)(id x))predicate;
每當(dāng)stream產(chǎn)生一個值都會詢問predicate,當(dāng)predicate返回YES當(dāng)前值以及后續(xù)值才會被訂閱者接收到主经。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
return nil;
}] skipUntilBlock:^BOOL(id x) {
return [x isEqualToString:@"3"];
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 17:00:28.968933+0800 ReactiveCocoaTest[39904:958633] 3
2018-04-12 17:00:28.969232+0800 ReactiveCocoaTest[39904:958633] 4
2018-04-12 17:00:28.969613+0800 ReactiveCocoaTest[39904:958633] 5
- (instancetype)skipWhileBlock:(BOOL (^)(id x))predicate;
每當(dāng)stream產(chǎn)生一個值都會詢問predicate荣暮,當(dāng)predicate返回NO當(dāng)前值以及后續(xù)值才會被訂閱者接收到。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendNext:@"4"];
[subscriber sendNext:@"5"];
[subscriber sendCompleted];
return nil;
}] skipWhileBlock:^BOOL(id x) {
return [x isEqualToString:@"1"];
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 17:13:25.548610+0800 ReactiveCocoaTest[40829:978359] 2
2018-04-12 17:13:25.548842+0800 ReactiveCocoaTest[40829:978359] 3
2018-04-12 17:13:25.549123+0800 ReactiveCocoaTest[40829:978359] 4
2018-04-12 17:13:25.549322+0800 ReactiveCocoaTest[40829:978359] 5
- (instancetype)distinctUntilChanged;
每當(dāng)stream產(chǎn)生一個新的值都會與上一次產(chǎn)生的值進(jìn)行 lastValue == x || [x isEqual:lastValue] 判斷罩驻,如果返回YES則訂閱者不會接收到值穗酥。
例
RACSignal * signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"1"];
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
return nil;
}] distinctUntilChanged];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2018-04-12 17:16:13.919028+0800 ReactiveCocoaTest[40996:981741] 1
2018-04-12 17:16:13.919383+0800 ReactiveCocoaTest[40996:981741] 2
2018-04-12 17:16:13.919676+0800 ReactiveCocoaTest[40996:981741] 1