//signal1,signal2有任何一个被订阅,即x等于一个RACTuple
RACSignal
*signal1 = [
RACSignal
defer
:^
RACSignal
*{
NSLog
(
@"aaaa"
);
return [ RACSignal : @"hello111" ];
}];
RACSignal *signal2 = [ *{
@"bbbb" @"hello222" ];
return [ RACSignal : @"hello111" ];
}];
RACSignal *signal2 = [ *{
@"bbbb" @"hello222" ];
}];
*signal3 =[
combineLatest
:
@[
signal1,signal2
]
];
[signal3
subscribeNext
:^(
id
x) {
@"x = %@" ,x);
@"x = %@" ,x);
}];
//先处理signal2 再处理signal1,当两个信号都sendNext后,signal3才会触发
- (
*)zipWith:(
*)signal
createSignal
@H_301_155@RACDisposable
*(
<
RACSubscriber
> subscriber) {
@"bbbbb" );
[subscriber sendNext @"asdfasdf" ];
[subscriber sendCompleted ];
return nil ;
}];
*signal3 = [signal2 zipWith :[signal1 logAll ]];
[signal3 );
} completed :^{
@"asdfasdfsdf" );
@"bbbbb" );
[subscriber sendNext @"asdfasdf" ];
[subscriber sendCompleted ];
return nil ;
}];
*signal3 = [signal2 zipWith :[signal1 logAll ]];
[signal3 );
} completed :^{
@"asdfasdfsdf" );
}];
//
:与
zipWith
:实际上结果是一样的.都是等到所有的signal被sendNext后,才会触发
//concat
concat
]];
/// Subscribes to `signal` when the source signal completes.
- (RACSignal *)concat:(*)signal;
当signal2被sendCompleted后,就去订阅signal1
RACSignal
*signal1 = [
RACSignal
defer
:^
RACSignal
*{
NSLog ( @"print signal1" );
return [ RACSignal return : @"signal1" ];
}];
RACSignal *signal2 = [ @"print signal2" );
@"signal2" ];
}];
RACSignal *signal3 = [signal1 concat :signal2];
[signal3 subscribeNext :^( id x) {
@"%@" ,x);
NSLog ( @"print signal1" );
return [ RACSignal return : @"signal1" ];
}];
RACSignal *signal2 = [ @"print signal2" );
@"signal2" ];
}];
RACSignal *signal3 = [signal1 concat :signal2];
[signal3 subscribeNext :^( id x) {
@"%@" ,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
.viewmodel,secCodeimageFile)
skip
1
]
map
:^
value) {
@"secCodeimageFile == %@" [[ UIImage alloc ] initWithContentsOfFile :value];
@"secCodeimageFile == %@" [[ UIImage alloc ] initWithContentsOfFile :value];
//
secCodeimageFile第一次为nil,可以通过skip跳过
//catch
/// Subscribes to the returned signal when an error occurs.
*)catch:(* (^)(NSError *error))catchBlock;
> subscriber) {
[subscriber sendError :[ NSError errorWithDomain @"my fault" code 100 userInfo : nil ]];
RACDisposable disposableWithBlock @"done" );
}];
}];
*signal2 = [signal1 catch *( NSError *error) {
@"catch error" @"idiot" ];
}];
[signal2 }];
[subscriber sendError :[ NSError errorWithDomain @"my fault" code 100 userInfo : nil ]];
RACDisposable disposableWithBlock @"done" );
}];
}];
*signal2 = [signal1 catch *( NSError *error) {
@"catch error" @"idiot" ];
}];
[signal2 }];
打个比方,如果要为服务器上某个商品点赞+1,但是出现了网络不同,此时,就要把UserDefault里的值减1.
/// Subscribes to the given signal when an error occurs.
*)catchTo:(*)signal;
catchTo
@"my falut"
]];
[signal2
[signal2
catch与
catchTo的目标是相同的,区别在于catch提供了一个处理error的机会,而catchTo直接无视error
//try
*)
try
:(
BOOL
(^)(
value,
NSError
**errorPtr))tryBlock;
*signal1 = [[
> subscriber) {
// 处理一个网络请求 , 当成功后把结果 okok 发送出去
[subscriber @"okok" );
}];
}] try ( NSString *s,209)"> * __autoreleasing *errorPtr) {
在这里尝试判断 signal 的结果 当收到了 Next 后 判断其值 如果结果与预期一样就 告诉订阅者
比如网络请求的结果是对的
if ([s hasPrefix @"ok" ]) {
YES ;
} else {
NO ;
}
}];
[signal1 id x) {
// 处理一个网络请求 , 当成功后把结果 okok 发送出去
[subscriber @"okok" );
}];
}] try ( NSString *s,209)"> * __autoreleasing *errorPtr) {
在这里尝试判断 signal 的结果 当收到了 Next 后 判断其值 如果结果与预期一样就 告诉订阅者
比如网络请求的结果是对的
if ([s hasPrefix @"ok" ]) {
YES ;
} else {
NO ;
}
}];
[signal1 id x) {
NSLog(@“subscribed.%@“,x //x == okok
}];
*)tryMap:(
**errorPtr))mapBlock
//delay
*)delay:(
NSTimeInterval
)interval
//sendNext后,再触发subscriber
//deliverOn
*)deliverOn:(
RACScheduler
*)scheduler
mainThreadScheduler
//订阅者将在main thread创建的工作队列里收到sendNext
//if:then:else:
@NO
@"hello222"
*signal3 = [
@"cccc"
@"hello333"
];
}];
[[ :signal1 then :signal2 else :signal3] id x) {
}];
[[ :signal1 then :signal2 else :signal3] id x) {
NSLog(@"subscribed. %@"//如果signal1sendNext:@YES,就执行signal2的内容,否则就是signal3
startWith:
RAC
(
self
.intervalTextField,text) = [[[
interval
:
1
onScheduler
:[
RACScheduler
mainThreadScheduler
]]
startWith
:
@"hello"
]
map
:^
id
(
id
value) {
NSString stringWithFormat : @"text %d" ,count++];
NSString stringWithFormat : @"text %d" ,count++];
}];
第一次拿到的值为”hello”,第二个才是text 0
RACAble/
RACAbleWithStart
反向绑定变量,当bindstring发生变化时,intervalTextField.text也会随着改变,但是反过来就不行
RACAbleWithStart
(
self
.bindString);
RACAble 只是绑定,
RACAbleWithStart是绑定后,立即对其赋值
merge/
combineLatest
:
RACSignal
*combinding = [
merge
:
@[self
.
textField1
.
rac_textSignal
,
self
.
textField2
.
rac_textSignal
]
];
[combinding @"%@" ,x);
} completed :^{
@"completed." );
[combinding @"%@" ,x);
} completed :^{
@"completed." );
}];
共同点:当任何一个信号被触发,combinding都会被调起
不同点:merge时x只是被触发的textField内容,combineLatest会把两个textField的值用一个tuple来传入x
RACMulticastConnection public connect
RACSignal
*signal1 = [
RACSignal
defer
:^
*{
NSLog ( @"print signal1" );
return [ RACSignal return : @"hello" ];
}];
[signal1 subscribeNext :^( id x) {
@"first %@" @"second %@" }];
NSLog ( @"print signal1" );
return [ RACSignal return : @"hello" ];
}];
[signal1 subscribeNext :^( id x) {
@"first %@" @"second %@" }];
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
那么,我打算某个网络操作只做一次,然后多个订阅者都可以收到消息,怎么做?
@"signal1"
];
}];
RACMulticastConnection *connection = [signal1 publish ];
[connection. signal subscribeNext @"first next value = %@" @"second next value = %@" [connection connect];
}];
RACMulticastConnection *connection = [signal1 publish ];
[connection. signal subscribeNext @"first next value = %@" @"second next value = %@" [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=[selfpopularURLRequest];
return[[[[[[NSURLConnectionrac_sendAsynchronousRequest:request]
reduceEach:^id(NSURLResponse*response,NSData*data){
returndata;
}]
deliverOn:[RACSchedulermainThreadScheduler]]
map:^id(NSData*data){
idresults=[NSJSONSerializationJSONObjectWithData:dataoptions:0error:nil];
return[[[results[@"photos"]rac_sequence]
map:^id(NSDictionary*photoDictionary){
FRPPhotoModel*model=[FRPPhotoModelnew];
[selfconfigurePhotoModel:modelwithDictionary:photoDictionary];
[selfdownloadThumbnailForPhotoModel:model];
returnmodel;
}]array];
}]publish]autoconnect];
}
这里使用到了publish与
auto connect,我的理解是publish返回的是一个
RACMulticastConnection
这是一个连接多个订阅者的handle
希望自己将来能看懂.
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
]
@"x1 == %@"
@"x2 == %@"
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
(
value) {
[value length ] > 3 ;
}] map value;
}] array ];
[value length ] > 3 ;
}] map value;
}] array ];
@"result = %@"
timeout
*signal =
[ createSignal RACDisposable *( < RACSubscriber > subscriber) {
RACDisposable *disposable = [ RACDisposable new ];
dispatch_async dispatch_get_global_queue DISPATCH_QUEUE_PRIORITY_DEFAULT 0 ),^{
@"Start iterating..." for ( int i = ; i < 200 && !disposable. isDisposed ; i++) {
@"Send %i to subscriber" : @( i ) ];
[ NSThread sleepForTimeInterval 0.1 ];
}
if (!disposable. ) {
@"Send completed to subscriber" );
[subscriber ];
}
});
disposable;
}];
@"About to subscribe" );
[[[signal
deliverOn :[ RACScheduler mainThreadScheduler ]]
timeout 1.0 onScheduler @"Got next: %@" error :^( NSError *error) {
@"Error (timeout): %@" localizedDescription ]);
} completed :^{
@"Completed" );
[ createSignal RACDisposable *( < RACSubscriber > subscriber) {
RACDisposable *disposable = [ RACDisposable new ];
dispatch_async dispatch_get_global_queue DISPATCH_QUEUE_PRIORITY_DEFAULT 0 ),^{
@"Start iterating..." for ( int i = ; i < 200 && !disposable. isDisposed ; i++) {
@"Send %i to subscriber" : @( i ) ];
[ NSThread sleepForTimeInterval 0.1 ];
}
if (!disposable. ) {
@"Send completed to subscriber" );
[subscriber ];
}
});
disposable;
}];
@"About to subscribe" );
[[[signal
deliverOn :[ RACScheduler mainThreadScheduler ]]
timeout 1.0 onScheduler @"Got next: %@" error :^( NSError *error) {
@"Error (timeout): %@" localizedDescription ]);
} completed :^{
@"Completed" );
}];
如果在1秒钟之内没有收到sendCompleted,那么timeout将会发送一个error出来.参考
http://spin.atomicobject.com/2014/09/25/timeouts-in-reactivecocoa/
@weakify(self);
RACSignal*enabled=[[RACObserve,viewmodels)
//Map_each_arrayofviewmodelstoasignaldeterminingwhetherthecommand//shouldbeenabled.
map:^(NSArray{
RACSequenceselectionSignals[[.rac_sequence
viewmodelviewmodel
//RACObserve()implicitlyretains`self`,soweneedtoavoid //aretaincycle. @strongify
//Observeeachviewmodel's`isSelected`propertyforchanges.
returnisSelected
}]
//EnsurewealwayshaveoneYESforthe-andbelow.
startWith:[return:@YES]];
//SendsYESwheneveralloftheviewmodelsareselected,NOotherwise.
combineLatest:]
and];
//Then,ensurethatweonlysubscribetothe_latest_signalreturnedfrom//theblockabove(i.e.,theobservationsfromthelatest`viewmodels`).
switchToLatest];
观察NSArray里所有对象里的一个Bool变量
倒数计时3秒,再开始录音10秒
__block
NSInteger
second =
;
RACSignal *timer = [[[ interval 1 ]] take value) {
@"ready time = %ld" return @YES ;
}];
*record = [ > subscriber) {
DDLogDebug @"start recording." );
*signal = [[ 10 ];
*disposable = [signal @"recording sec %ld" :x];
} @"record completed." ];
}];
disposable;
}];
*chianSignal = [timer concat :record];
[chianSignal @"x = %@" @"all done" }];
RACSignal *timer = [[[ interval 1 ]] take value) {
@"ready time = %ld" return @YES ;
}];
*record = [ > subscriber) {
DDLogDebug @"start recording." );
*signal = [[ 10 ];
*disposable = [signal @"recording sec %ld" :x];
} @"record completed." ];
}];
disposable;
}];
*chianSignal = [timer concat :record];
[chianSignal @"x = %@" @"all done" }];
//
*)initially:(
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]; /// }] /// // 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]; /// }] /// // 1. First,acquire write lock. /// [writeLock lock]; /// finally:^{ /// [writeLock unlock];
/// }];
//
*)bufferWithTime:(
NSTimeInterval
)interval onScheduler:(
RACScheduler
*)scheduler
当single要在很短的时候内吐出N个value,
bufferWithTime可以以interval的间隔分割它们.
它确保了每interval时间内,只收到一次next,value为期间的所有的内容tuple
//-replay 总是收取最后的内容,而并不执行signal
@H_157_2301@
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) "S2: %@",10)">// Subscriber 3 (S3) "S3: %@",0)">];
Incrementnumto:1
Startsubscriptions
S1:1
S2:1
原文链接:https://www.f2er.com/react/307261.htmlStartsubscriptions
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:(
running,
id
next))reduceBlock
*)aggregateWithStart:(
)start reduce:(
)start reduceWithIndex:(
NSUInteger
))reduceBlock
这三个货的作用,收到signal发送过来的next值,通过reduce
RACSequence
*seq = [
@"a b c d e f"
componentsSeparatedByString
:
@" "
].
rac_sequence
;
[[seq. signal aggregateWithStart :[ NSMutableSet set ] reduce :^ id ( id next) {
NSLog ( @"running = %@,next = %@" NSString *newString = [next stringByAppendingString :next];
[running addObject :newString];
return running;
}] subscribeNext :^( x) {
@"x = %@" completed :^{
@"completed" );
[[seq. signal aggregateWithStart :[ NSMutableSet set ] reduce :^ id ( id next) {
NSLog ( @"running = %@,next = %@" NSString *newString = [next stringByAppendingString :next];
[running addObject :newString];
return running;
}] subscribeNext :^( x) {
@"x = %@" completed :^{
@"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,next = d
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
dd,next = e
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
ee,next = f
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] x = {(
cc,
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,next = d
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
dd,next = e
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] running = {(
cc,
ee,next = f
2015-07-09 16:19:42.557 DemoCategorizer[74923:2050916] x = {(
cc,
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
value) {
return @"s2" ;
}];
RACSignal *s3 = [s2 throttle 3 ]; //3 秒钟之内 没有第二个 sendNext,167)">即 s3 sendNext
[s3 @"%@" }];
return @"s2" ;
}];
RACSignal *s3 = [s2 throttle 3 ]; //3 秒钟之内 没有第二个 sendNext,167)">即 s3 sendNext
[s3 @"%@" }];