//signal1,signal2有任何一个被订阅,即x等于一个RACTuple
RACSignal
*signal1 = [
RACSignal
defer
:^
RACSignal
*{
NSLog
(
@"aaaa"
);
return [ RACSignal return : @"hello111" ];
}];
RACSignal *signal2 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"bbbb" );
return [ RACSignal return : @"hello222" ];
return [ RACSignal return : @"hello111" ];
}];
RACSignal *signal2 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"bbbb" );
return [ RACSignal return : @"hello222" ];
}];
RACSignal
*signal3 =[
RACSignal
combineLatest
:
@[
signal1,signal2
]
];
[signal3
subscribeNext
:^(
id
x) {
NSLog ( @"x = %@" ,x);
NSLog ( @"x = %@" ,x);
}];
//先处理signal2 再处理signal1 ,当两个信号都sendNext后,signal3才会触发
- (
RACSignal
*)zipWith:(
RACSignal
*)signal
RACSignal
*signal1 = [
RACSignal
defer
:^
RACSignal
*{
NSLog ( @"aaaa" );
return [ RACSignal return : @"hello111" ];
}];
RACSignal *signal2 = [ RACSignal createSignal :^ RACDisposable *( id < RACSubscriber > subscriber) {
NSLog ( @"bbbbb" );
[subscriber sendNext : @"asdfasdf" ];
[subscriber sendCompleted ];
return nil ;
}];
RACSignal *signal3 = [signal2 zipWith :[signal1 logAll ]];
[signal3 subscribeNext :^( id x) {
NSLog ( @"asdfasdf" );
} completed :^{
NSLog ( @"asdfasdfsdf" );
NSLog ( @"aaaa" );
return [ RACSignal return : @"hello111" ];
}];
RACSignal *signal2 = [ RACSignal createSignal :^ RACDisposable *( id < RACSubscriber > subscriber) {
NSLog ( @"bbbbb" );
[subscriber sendNext : @"asdfasdf" ];
[subscriber sendCompleted ];
return nil ;
}];
RACSignal *signal3 = [signal2 zipWith :[signal1 logAll ]];
[signal3 subscribeNext :^( id x) {
NSLog ( @"asdfasdf" );
} completed :^{
NSLog ( @"asdfasdfsdf" );
}];
//
RACSignal
combineLatest
:与
zipWith
:实际上结果是一样的.都是等到所有的signal被sendNext后,才会触发
//concat
RACSignal
*signal3 = [signal2
concat
:[signal1
logAll
]];
/// Subscribes to `signal` when the source signal completes.
- (RACSignal *)concat:(RACSignal *)signal;
当signal2 被sendCompleted后,就去订阅signal1
RACSignal
*signal1 = [
RACSignal
defer
:^
RACSignal
*{
NSLog ( @"print signal1" );
return [ RACSignal return : @"signal1" ];
}];
RACSignal *signal2 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"print signal2" );
return [ RACSignal return : @"signal2" ];
}];
RACSignal *signal3 = [signal1 concat :signal2];
[signal3 subscribeNext :^( id x) {
NSLog ( @"%@" ,x);
NSLog ( @"print signal1" );
return [ RACSignal return : @"signal1" ];
}];
RACSignal *signal2 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"print signal2" );
return [ RACSignal return : @"signal2" ];
}];
RACSignal *signal3 = [signal1 concat :signal2];
[signal3 subscribeNext :^( id x) {
NSLog ( @"%@" ,x);
}];
2015-06-03 13:23:00.381 DemoCategorizer[21572:2556481] print signal1
2015-06-03 13:23:07.385 DemoCategorizer[21572:2556481] signal1
2015-06-03 13:23:07.385 DemoCategorizer[21572:2556481] print signal2
2015-06-03 13:23:07.385 DemoCategorizer[21572:2556481] signal1
2015-06-03 13:23:07.385 DemoCategorizer[21572:2556481] print signal2
2015-06-03 13:23:16.748 DemoCategorizer[21572:2556481] signal2
//skip
skip:(
NSUInteger
)skipCount
//跳过第
skipCount
个sendNext,从后面取
RAC
(
self
.secCodeImageView,image) = [[
RACObserve
(
self
.viewModel,secCodeimageFile)
skip
:
1
]
map
:^
id
(
id
value) {
NSLog ( @"secCodeimageFile == %@" ,value);
return [[ UIImage alloc ] initWithContentsOfFile :value];
NSLog ( @"secCodeimageFile == %@" ,value);
return [[ UIImage alloc ] initWithContentsOfFile :value];
}];
//
secCodeimageFile第一次为nil,可以通过skip跳过
//catch
/// Subscribes to the returned signal when an error occurs.
- (RACSignal *)catch:(RACSignal * (^)(NSError *error))catchBlock;
RACSignal
*signal1 = [
RACSignal
createSignal
:^
RACDisposable
*(
id
<
RACSubscriber
> subscriber) {
[subscriber sendError :[ NSError errorWithDomain : @"my fault" code : 100 userInfo : nil ]];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}];
RACSignal *signal2 = [signal1 catch :^ RACSignal *( NSError *error) {
NSLog ( @"catch error" );
return [ RACSignal return : @"idiot" ];
}];
[signal2 subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
[subscriber sendError :[ NSError errorWithDomain : @"my fault" code : 100 userInfo : nil ]];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}];
RACSignal *signal2 = [signal1 catch :^ RACSignal *( NSError *error) {
NSLog ( @"catch error" );
return [ RACSignal return : @"idiot" ];
}];
[signal2 subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
}];
//catch用于,封装一个错误处理机制的signal,也就是当signal1出现了错误,将创建一个新的错误处理signal2,完成后并处理订阅者的流程
打个比方,如果要为服务器上某个商品点赞+1,但是出现了网络不同,此时,就要把UserDefault里的值减1.
/// Subscribes to the given signal when an error occurs.
- (RACSignal *)catchTo:(RACSignal *)signal;
RACSignal
*signal1 = [
RACSignal
createSignal
:^
RACDisposable
*(
id
<
RACSubscriber
> subscriber) {
[subscriber sendError :[ NSError errorWithDomain : @"my fault" code : 100 userInfo : nil ]];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}];
RACSignal *signal2 = [signal1 catchTo :[ RACSignal return : @"my falut" ]];
[signal2 subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
[subscriber sendError :[ NSError errorWithDomain : @"my fault" code : 100 userInfo : nil ]];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}];
RACSignal *signal2 = [signal1 catchTo :[ RACSignal return : @"my falut" ]];
[signal2 subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
}];
catch与
catchTo的目标是相同的,区别在于catch提供了一个处理error的机会,而catchTo直接无视error
//try
- (
RACSignal
*)
try
:(
BOOL
(^)(
id
value,
NSError
**errorPtr))tryBlock;
RACSignal
*signal1 = [[
RACSignal
createSignal
:^
RACDisposable
*(
id
<
RACSubscriber
> subscriber) {
// 处理一个网络请求 , 当成功后把结果 okok 发送出去
[subscriber sendNext : @"okok" ];
[subscriber sendCompleted ];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}] try :^ BOOL ( NSString *s, NSError * __autoreleasing *errorPtr) {
// 在这里尝试判断 signal 的结果 , 当收到了 Next 后 , 判断其值 , 如果结果与预期一样就 , 告诉订阅者
// 比如网络请求的结果是对的
if ([s hasPrefix : @"ok" ]) {
return YES ;
} else {
return NO ;
}
}];
[signal1 subscribeNext :^( id x) {
// 处理一个网络请求 , 当成功后把结果 okok 发送出去
[subscriber sendNext : @"okok" ];
[subscriber sendCompleted ];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}] try :^ BOOL ( NSString *s, NSError * __autoreleasing *errorPtr) {
// 在这里尝试判断 signal 的结果 , 当收到了 Next 后 , 判断其值 , 如果结果与预期一样就 , 告诉订阅者
// 比如网络请求的结果是对的
if ([s hasPrefix : @"ok" ]) {
return YES ;
} else {
return NO ;
}
}];
[signal1 subscribeNext :^( id x) {
NSLog(@“subscribed.%@“,x);
//x == okok
}];
- (
RACSignal
*)tryMap:(
id
(^)(
id
value,
NSError
**errorPtr))mapBlock
try与tryMap都是为了判断一个signal是否sendNext,区别在于try可以根据结果来决定是否继续并且把kook发送给订阅方,而tryMap则会对值做一个转换再传给订阅方
//delay
- (
RACSignal
*)delay:(
NSTimeInterval
)interval
//sendNext后,再触发subscriber
//deliverOn
- (
RACSignal
*)deliverOn:(
RACScheduler
*)scheduler
deliverOn
:[
RACScheduler
scheduler
]
//订阅者将在ReactiveCocoa创建的工作队列里收到sendNext
deliverOn
:[
RACScheduler
mainThreadScheduler
]
//订阅者将在main thread创建的工作队列里收到sendNext
//if:then:else:
RACSignal
*signal1 = [
RACSignal
createSignal
:^
RACDisposable
*(
id
<
RACSubscriber
> subscriber) {
[subscriber sendNext : @NO ];
[subscriber sendCompleted ];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}];
RACSignal *signal2 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"bbbb" );
return [ RACSignal return : @"hello222" ];
}];
RACSignal *signal3 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"cccc" );
return [ RACSignal return : @"hello333" ];
}];
[[ RACSignal if :signal1 then :signal2 else :signal3] subscribeNext :^( id x) {
[subscriber sendNext : @NO ];
[subscriber sendCompleted ];
return [ RACDisposable disposableWithBlock :^{
NSLog ( @"done" );
}];
}];
RACSignal *signal2 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"bbbb" );
return [ RACSignal return : @"hello222" ];
}];
RACSignal *signal3 = [ RACSignal defer :^ RACSignal *{
NSLog ( @"cccc" );
return [ RACSignal return : @"hello333" ];
}];
[[ RACSignal if :signal1 then :signal2 else :signal3] subscribeNext :^( id x) {
NSLog(@"subscribed. %@",x);
//如果signal1 sendNext:@YES,就执行signal2的内容,否则就是signal3
startWith:
RAC
(
self
.intervalTextField,text) = [[[
RACSignal
interval
:
1
onScheduler
:[
RACScheduler
mainThreadScheduler
]]
startWith
:
@"hello"
]
map
:^
id
(
id
value) {
return [ NSString stringWithFormat : @"text %d" ,count++];
return [ NSString stringWithFormat : @"text %d" ,count++];
}];
第一次拿到的值为”hello”,第二个才是text 0
RACAble/
RACAbleWithStart
反向绑定变量,当bindstring发生变化时,intervalTextField.text也会随着改变,但是反过来就不行
RAC
(
self
.intervalTextField,text) =
RACAbleWithStart
(
self
.bindString);
RACAble 只是绑定,
RACAbleWithStart是绑定后,立即对其赋值
}];
merge/
combineLatest
:
RACSignal
*combinding = [
RACSignal
merge
:
@[self
.
textField1
.
rac_textSignal
,
self
.
textField2
.
rac_textSignal
]
];
[combinding subscribeNext :^( id x) {
NSLog ( @"%@" ,x);
} completed :^{
NSLog ( @"completed." );
[combinding subscribeNext :^( id x) {
NSLog ( @"%@" ,x);
} completed :^{
NSLog ( @"completed." );
}];
共同点:当任何一个信号被触发,combinding都会被调起
不同点:merge时x只是被触发的textField内容,combineLatest会把两个textField的值用一个tuple来传入x
RACMulticastConnection public connect
当一个信号被订阅了几次,那么它将会执行几次,见下方代码:
RACSignal
*signal1 = [
RACSignal
defer
:^
RACSignal
*{
NSLog ( @"print signal1" );
return [ RACSignal return : @"hello" ];
}];
[signal1 subscribeNext :^( id x) {
NSLog ( @"first %@" ,x);
}];
[signal1 subscribeNext :^( id x) {
NSLog ( @"second %@" ,x);
NSLog ( @"print signal1" );
return [ RACSignal return : @"hello" ];
}];
[signal1 subscribeNext :^( id x) {
NSLog ( @"first %@" ,x);
}];
[signal1 subscribeNext :^( id x) {
NSLog ( @"second %@" ,x);
}];
2015-06-05 14:35:38.149 DemoCategorizer[15252:2226982] print signal1
2015-06-05 14:35:38.149 DemoCategorizer[15252:2226982] first hello
2015-06-05 14:35:38.149 DemoCategorizer[15252:2226982] print signal1
2015-06-05 14:35:38.149 DemoCategorizer[15252:2226982] first hello
2015-06-05 14:35:38.149 DemoCategorizer[15252:2226982] print signal1
2015-06-05 14:35:38.149 DemoCategorizer[15252:2226982] second hello
那么,我打算某个网络操作只做一次,然后多个订阅者都可以收到消息,怎么做?
RACSignal
*signal1 = [
RACSignal
defer
:^
RACSignal
*{
NSLog ( @"print signal1" );
return [ RACSignal return : @"signal1" ];
}];
RACMulticastConnection *connection = [signal1 publish ];
[connection. signal subscribeNext :^( id x) {
NSLog ( @"first next value = %@" ,x);
}];
[connection. signal subscribeNext :^( id x) {
NSLog ( @"second next value = %@" ,x);
}];
NSLog ( @"print signal1" );
return [ RACSignal return : @"signal1" ];
}];
RACMulticastConnection *connection = [signal1 publish ];
[connection. signal subscribeNext :^( id x) {
NSLog ( @"first next value = %@" ,x);
}];
[connection. signal subscribeNext :^( id x) {
NSLog ( @"second next value = %@" ,x);
}];
[connection connect];
2015-06-05 14:38:48.528 DemoCategorizer[15848:2239991] print signal1
2015-06-05 14:38:48.528 DemoCategorizer[15848:2239991] first next value = signal1
2015-06-05 14:38:48.528 DemoCategorizer[15848:2239991] first next value = signal1
2015-06-05 14:38:48.528 DemoCategorizer[15848:2239991] second next value = signal1
signal1只是被执行了一次,神奇不? 详见
http://www.jianshu.com/p/a0a821a2480f
+(RACSignal*)importPhotos{
NSURLRequest *request = [self popularURLRequest];
return [[[[[[NSURLConnection rac_sendAsynchronousRequest:request]
reduceEach:^id(NSURLResponse *response, NSData *data){
return data;
}]
deliverOn:[RACSchedulermainThreadScheduler]]
map:^id(NSData*data){
id results = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
return [[[results[@"photos"] rac_sequence]
map:^id(NSDictionary *photoDictionary){
FRPPhotoModel *model = [FRPPhotoModel new];
[self configurePhotoModel:model withDictionary:photoDictionary];
[self downloadThumbnailForPhotoModel:model];
return model;
}] array];
}] publish] autoconnect];
}
这里使用到了publish与
auto connect,我的理解是publish返回的是一个
RACMulticastConnection
这是一个连接多个订阅者的handle
autoconnect的目的是返回一个RACSignal,它连接着多个订阅者,只要有一个订阅者订阅了该信号,那么该信号只会做一次,然后分发给多个订阅者结果.
希望自己将来能看懂.
RACReplaySubject
注意区分RACSubject和其子类RACReplaySubject的不同。RACReplaySubject只能被订阅一次,这避免了重复的重做。replay subject会存储返回的值,并把他们发送给新的订阅者-这正是我们需要的。
- (
RACReplaySubject
*)importPhotos{
RACReplaySubject *subject = [[ RACReplaySubject alloc ] init ];
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 5 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
[subject sendNext : @"myword" ];
[subject sendCompleted ];
});
return subject;
RACReplaySubject *subject = [[ RACReplaySubject alloc ] init ];
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 5 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
[subject sendNext : @"myword" ];
[subject sendCompleted ];
});
return subject;
}
[[
self
importPhotos
]
subscribeNext
:^(
id
x) {
NSLog ( @"x1 == %@" ,x);
}];
[[ self importPhotos ] subscribeNext :^( id x) {
NSLog ( @"x2 == %@" ,x);
NSLog ( @"x1 == %@" ,x);
}];
[[ self importPhotos ] subscribeNext :^( id x) {
NSLog ( @"x2 == %@" ,x);
}];
2015-06-05 14:58:52.344 DemoCategorizer[19469:2329348] x1 == myword
2015-06-05 14:58:52.345 DemoCategorizer[19469:2329348] x2 == myword
注意两次时间几乎是一样的,原因在于RACReplaySubject把最后一次执行结果保存了下来.
array
取出长度大于3的字符串,再组成一个array
NSArray
*result = [[[[
@[
@"aaaa"
,
@"bb"
,
@"ccc"
,
@"dd"
,
@"ffffff"
]
rac_sequence
]
filter
:^
BOOL
(
id
value) {
return [value length ] > 3 ;
}] map :^ id ( id value) {
return value;
}] array ];
return [value length ] > 3 ;
}] map :^ id ( id value) {
return value;
}] array ];
NSLog(@"result = %@",result);
timeout
RACSignal
*signal =
[ RACSignal createSignal :^ RACDisposable *( id < RACSubscriber > subscriber) {
RACDisposable *disposable = [ RACDisposable new ];
dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 ), ^{
NSLog ( @"Start iterating..." );
for ( int i = 0 ; i < 200 && !disposable. isDisposed ; i++) {
NSLog ( @"Send %i to subscriber" , i);
[subscriber sendNext : @( i ) ];
[ NSThread sleepForTimeInterval : 0.1 ];
}
if (!disposable. isDisposed ) {
NSLog ( @"Send completed to subscriber" );
[subscriber sendCompleted ];
}
});
return disposable;
}];
NSLog ( @"About to subscribe" );
[[[signal
deliverOn :[ RACScheduler mainThreadScheduler ]]
timeout : 1.0 onScheduler :[ RACScheduler mainThreadScheduler ]]
subscribeNext :^( id x) {
NSLog ( @"Got next: %@" , x);
} error :^( NSError *error) {
NSLog ( @"Error (timeout): %@" , [error localizedDescription ]);
} completed :^{
NSLog ( @"Completed" );
[ RACSignal createSignal :^ RACDisposable *( id < RACSubscriber > subscriber) {
RACDisposable *disposable = [ RACDisposable new ];
dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 ), ^{
NSLog ( @"Start iterating..." );
for ( int i = 0 ; i < 200 && !disposable. isDisposed ; i++) {
NSLog ( @"Send %i to subscriber" , i);
[subscriber sendNext : @( i ) ];
[ NSThread sleepForTimeInterval : 0.1 ];
}
if (!disposable. isDisposed ) {
NSLog ( @"Send completed to subscriber" );
[subscriber sendCompleted ];
}
});
return disposable;
}];
NSLog ( @"About to subscribe" );
[[[signal
deliverOn :[ RACScheduler mainThreadScheduler ]]
timeout : 1.0 onScheduler :[ RACScheduler mainThreadScheduler ]]
subscribeNext :^( id x) {
NSLog ( @"Got next: %@" , x);
} error :^( NSError *error) {
NSLog ( @"Error (timeout): %@" , [error localizedDescription ]);
} completed :^{
NSLog ( @"Completed" );
}];
如果在1秒钟之内没有收到sendCompleted,那么timeout将会发送一个error出来.参考
http://spin.atomicobject.com/2014/09/25/timeouts-in-reactivecocoa/
@weakify(self);
RACSignal *enabled = [[RACObserve(self, viewModels)
// Map _each_ array of view models to a signal determining whether the command
// should be enabled.
map:^(NSArray *viewModels) {
RACSequence *selectionSignals = [[viewModels.rac_sequence
map:^(ViewModel *viewModel) {
// RACObserve() implicitly retains `self`, so we need to avoid
// a retain cycle.
@strongify(self);
// Observe each view model's `isSelected` property for changes.
return RACObserve(viewModel, isSelected);
}]
// Ensure we always have one YES for the -and below.
startWith:[RACSignal return:@YES]];
// Sends YES whenever all of the view models are selected, NO otherwise.
return [[RACSignal
combineLatest:selectionSignals]
and];
}]
// Then, ensure that we only subscribe to the _latest_ signal returned from
// the block above (i.e., the observations from the latest `viewModels`).
switchToLatest];
观察NSArray里所有对象里的一个Bool变量
倒数计时3秒,再开始录音10秒
__block
NSInteger
second =
3
;
RACSignal *timer = [[[ RACSignal interval : 1 onScheduler :[ RACScheduler mainThreadScheduler ]] take : 3 ] map :^ id ( id value) {
NSLog ( @"ready time = %ld" ,second--);
return @YES ;
}];
RACSignal *record = [ RACSignal createSignal :^ RACDisposable *( id < RACSubscriber > subscriber) {
DDLogDebug ( @"start recording." );
RACSignal *signal = [[ RACSignal interval : 1 onScheduler :[ RACScheduler mainThreadScheduler ]] take : 10 ];
RACDisposable *disposable = [signal subscribeNext :^( id x) {
NSLog ( @"recording sec %ld" ,second++);
[subscriber sendNext :x];
} completed :^{
NSLog ( @"record completed." );
[subscriber sendCompleted ];
}];
return disposable;
}];
RACSignal *chianSignal = [timer concat :record];
[chianSignal subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
} completed :^{
NSLog ( @"all done" );
RACSignal *timer = [[[ RACSignal interval : 1 onScheduler :[ RACScheduler mainThreadScheduler ]] take : 3 ] map :^ id ( id value) {
NSLog ( @"ready time = %ld" ,second--);
return @YES ;
}];
RACSignal *record = [ RACSignal createSignal :^ RACDisposable *( id < RACSubscriber > subscriber) {
DDLogDebug ( @"start recording." );
RACSignal *signal = [[ RACSignal interval : 1 onScheduler :[ RACScheduler mainThreadScheduler ]] take : 10 ];
RACDisposable *disposable = [signal subscribeNext :^( id x) {
NSLog ( @"recording sec %ld" ,second++);
[subscriber sendNext :x];
} completed :^{
NSLog ( @"record completed." );
[subscriber sendCompleted ];
}];
return disposable;
}];
RACSignal *chianSignal = [timer concat :record];
[chianSignal subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
} completed :^{
NSLog ( @"all done" );
}];
//
- (
RACSignal
*)initially:(
void
(^)(
void
))block
/// // Write new file, with backup.
/// [[[[fileManager
/// rac_createFileAtPath:path contents:data]
/// initially:^{
/// // 2. Second, backup current file
/// [fileManager moveItemAtPath:path toPath:backupPath error:nil];
/// }]
/// initially:^{
/// // 1. First, acquire write lock.
/// [writeLock lock];
/// }]
/// finally:^{
/// [writeLock unlock];
/// [[[[fileManager
/// rac_createFileAtPath:path contents:data]
/// initially:^{
/// // 2. Second, backup current file
/// [fileManager moveItemAtPath:path toPath:backupPath error:nil];
/// }]
/// initially:^{
/// // 1. First, acquire write lock.
/// [writeLock lock];
/// }]
/// finally:^{
/// [writeLock unlock];
/// }];
//
- (
RACSignal
*)bufferWithTime:(
NSTimeInterval
)interval onScheduler:(
RACScheduler
*)scheduler
当single要在很短的时候内吐出N个value,
bufferWithTime可以以interval的间隔分割它们.
它确保了每interval时间内,只收到一次next,value为期间的所有的内容tuple
//-replay 总是收取最后的内容,而并不执行signal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | __block int num = 0; RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id subscriber) { num++; NSLog(@"Increment num to: %i", num); [subscriber sendNext:@(num)]; return nil; }] replay]; NSLog(@"Start subscriptions"); // Subscriber 1 (S1) [signal subscribeNext:^(id x) { NSLog(@"S1: %@", x); }]; // Subscriber 2 (S2) [signal subscribeNext:^(id x) { NSLog(@"S2: %@", x); }]; // Subscriber 3 (S3) [signal subscribeNext:^(id x) { NSLog(@"S3: %@", x); }]; |
Increment num to: 1
Start subscriptions
S1: 1
S2: 1
Start subscriptions
S1: 1
S2: 1
S3: 1
-replay 总是取出第一订阅者取到的
所有结果
-replayLast 总是取出第一个订阅者取到的
最后一个结果
-replayLazily有点说不上来
replayLazily does not subscribe to the signal immediately – it lazily waits until there is a “real” subscriber. But replay subscribes immediately. So as you point out, with replayLazily the “A” value would not be sent to subscribers of the signal because it was sent before there was anything listening.
- (
RACSignal
*)aggregateWithStartFactory:(
id
(^)(
void
))startFactory reduce:(
id
(^)(
id
running,
id
next))reduceBlock
- (
RACSignal
*)aggregateWithStart:(
id
)start reduce:(
id
(^)(
id
running,
id
next))reduceBlock
- (
RACSignal
*)aggregateWithStart:(
id
)start reduceWithIndex:(
id
(^)(
id
,
id
,
NSUInteger
))reduceBlock
这三个货的作用,收到signal发送过来的next值,通过reduce
RACSequence
*seq = [
@"a b c d e f"
componentsSeparatedByString
:
@" "
].
rac_sequence
;
[[seq. signal aggregateWithStart :[ NSMutableSet set ] reduce :^ id ( id running, id next) {
NSLog ( @"running = %@, next = %@" ,running,next);
NSString *newString = [next stringByAppendingString :next];
[running addObject :newString];
return running;
}] subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
} completed :^{
NSLog ( @"completed" );
[[seq. signal aggregateWithStart :[ NSMutableSet set ] reduce :^ id ( id running, id next) {
NSLog ( @"running = %@, next = %@" ,running,next);
NSString *newString = [next stringByAppendingString :next];
[running addObject :newString];
return running;
}] subscribeNext :^( id x) {
NSLog ( @"x = %@" ,x);
} completed :^{
NSLog ( @"completed" );
}];
output:
2015-07-09 16:19:42.556 DemoCategorizer[74923:2050916] running = {(
)}, next = a
2015-07-09 16:19:42.556 DemoCategorizer[74923:2050916] running = {(
aa
)}, next = b
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
aa,
bb
)}, next = c
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
aa,
bb
)}, next = d
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
dd,
aa,
bb
)}, next = e
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
dd,
aa,
ee,
bb
)}, next = f
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] x = {(
cc,
dd,
aa,
ee,
bb,
ff
)}
)}, next = a
2015-07-09 16:19:42.556 DemoCategorizer[74923:2050916] running = {(
aa
)}, next = b
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
aa,
bb
)}, next = c
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
aa,
bb
)}, next = d
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
dd,
aa,
bb
)}, next = e
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
dd,
aa,
ee,
bb
)}, next = f
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] x = {(
cc,
dd,
aa,
ee,
bb,
ff
)}
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] completed
直到set遍历完所有的值,最后由next吐出来
//throttle
RACSignal
*s2 = [[
RACSignal
interval
:
5
onScheduler
:[
RACScheduler
mainThreadScheduler
]]
map
:^
id
(
id
value) {
return @"s2" ;
}];
RACSignal *s3 = [s2 throttle : 3 ]; //3 秒钟之内 , 没有第二个 sendNext, 即 s3 sendNext
[s3 subscribeNext :^( id x) {
NSLog ( @"%@" ,x);
return @"s2" ;
}];
RACSignal *s3 = [s2 throttle : 3 ]; //3 秒钟之内 , 没有第二个 sendNext, 即 s3 sendNext
[s3 subscribeNext :^( id x) {
NSLog ( @"%@" ,x);
}];