项目地址:ReactiveObjC
1.键值观察--监听TF的值发生变化
- (void)demo1{
@weakify(self);
[self.tF.rac_textSignal subscribeNext:^(NSString *value) {
@strongify(self);
self.value = value;
}];
//当self.value的值变化时调用Block,这是用KVO的机制,RAC封装了KVO
[RACObserve(self, value) subscribeNext:^(NSString *value) {
NSLog(@"%@",value);
}];
}
2. map的使用
- (void)demo2{
//创建一个信号
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//这个信号里面有一个Next事件的玻璃球和一个complete事件的玻璃球
[subscriber sendNext:@"唱歌"];
[subscriber sendCompleted];
return nil;
}];
//对信号进行改进,当信号里面流的是唱歌.就改进为'跳舞'返还给self.value
RAC(self, tF.text) = [signalA map:^id(NSString *value) {
if ([value isEqualToString:@"唱歌"]) {
return @"跳舞";
}
return @"";
}];
}
3.filter使用,你向西,他就向东,他向左,你就向右。
- (void)demo3{
//创建两个通道,一个从A流出的通道A,和一个从B流出的通道B
RACChannelTerminal *channelA = RACChannelTo(self, value);
RACChannelTerminal *channelB = RACChannelTo(self,value2);
//改造通道A,使通过通道A的值,如果等于'西',就改为'东'
[[channelA map:^id(NSString *value) {
if ([value isEqualToString:@"西"]) {
NSLog(@"东");
return @"东";
}
NSLog(@"====== %@",value);
return value;
}] subscribe:channelB];//通道A流向B
//改造通道B,使通过通道B的值,如果等于'左',就改为'右'传出去
[[channelB map:^id(id value) {
if ([value isEqualToString:@"左"]) {
NSLog(@"右");
return @"右";
}
NSLog(@"====== %@",value);
return value;
}] subscribe:channelA];//通道B流向通道A
//KVO监听valueA的值的变化,过滤valueA的值,返回Yes表示通过
//只有value有值,才可通过
[[RACObserve(self, value) filter:^BOOL(id value) {
return value ? YES : NO;
}] subscribeNext:^(id x) {
NSLog(@"你向%@",x);
}];
//KVO监听value2的变化
[[RACObserve(self, value2) filter:^BOOL(id value) {
return value ? YES: NO;
}] subscribeNext:^(id x) {
NSLog(@"他向%@",x);
}];
//下面使value的值和value2的值发生改变
self.value = @"西";
self.value2 = @"左";
}
4.代理
/**
* RACSubject:信号提供者,自己可以充当信号,又能发送信号
创建方法:
1.创建RACSubject
2.订阅信号
3.发送信号
工作流程:
1.订阅信号,内部保存了订阅者,和订阅者相应block
2.当发送信号的,遍历订阅者,调用订阅者的nextBolck
注:如果订阅信号,必须在发送信号之前订阅信号,不然收不到信号,有利用区别RACReplaySubject
*/
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
RacSubjectController *racsub = [[RacSubjectController alloc] init];
racsub.subject = [RACSubject subject];
[racsub.subject subscribeNext:^(id x) {
NSLog(@"被通知了%@",x);
}];
[self.navigationController pushViewController:racsub animated:YES];
}
在RacSubjectController.h里面声明属性
@property (nonatomic, strong) RACSubject *subject;
.m里面进行数据的传递
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if (self.subject) {
[self.subject sendNext:@1];
}
}
5.广播
//发送通知
- (void)demo5{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//发送广播通知
[center postNotificationName:@"妇女之友" object:nil userInfo:@{@"技巧":@"用心听"}];
}
//接收通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//RAC的通知不需要我们手动移除
//注册广播通知
RACSignal *siganl = [center rac_addObserverForName:@"妇女之友" object:nil];
//设置接收通知的回调处理
[siganl subscribeNext:^(NSNotification *x) {
NSLog(@"技巧: %@",x.userInfo[@"技巧"]);
}];
6.两个信号串联,两个管串联,一个管处理完自己的东西,下一个管才开始处理自己的东西
- (void)demo6{
//创建一个信号管A
RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"吃饭"];
[subscriber sendCompleted];
return nil;
}];
//创建一个信号管B
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"吃的饱饱的,才可以睡觉的"];
[subscriber sendCompleted];
return nil;
}];
//串联管A和管B
RACSignal *concatSiganl = [siganlA concat:siganlB];
//串联后的接收端处理 ,两个事件,走两次,第一个打印siggnalA的结果,第二次打印siganlB的结果
[concatSiganl subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
7.并联,只要有一个管有东西,就可以打印
- (void)demo7{
//创建信号A
RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"纸厂污水"];
[subscriber sendCompleted];
return nil;
}];
//创建信号B
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"电镀厂污水"];
[subscriber sendCompleted];
return nil;
}];
//并联两个信号,根上面一样,分两次打印
RACSignal *mergeSiganl = [RACSignal merge:@[siganlA,siganlB]];
[mergeSiganl subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
8.组合,只有两个信号都有值,才可以组合
- (void)demo8{
//定义2个自定义信号
RACSubject *letters = [RACSubject subject];
RACSubject *numbers = [RACSubject subject];
//组合信号
[[RACSignal combineLatest:@[letters,numbers] reduce:^(NSString *letter, NSString *number){
return [letter stringByAppendingString:number];
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//自己控制发生信号值
[letters sendNext:@"A"];
[letters sendNext:@"B"];
[numbers sendNext:@"1"]; //打印B1
[letters sendNext:@"C"];//打印C1
[numbers sendNext:@"2"];//打印C2
}
9.合流压缩
- (void)demo9{
//创建信号A
RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"红"];
[subscriber sendCompleted];
return nil;
}];
//创建信号B
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"白"];
[subscriber sendCompleted];
return nil;
}];
//合流后处理的是压缩包,需要解压后才能取到里面的值
[[siganlA zipWith:siganlB] subscribeNext:^(id x) {
//解压缩
RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
NSLog(@"%@ %@",stringA, stringB);
}];
}
10.映射,我可以点石成金
- (void)demo10{
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}];
//对信号进行改造,改"石"成"金"
siganl = [siganl map:^id(NSString *value) {
if ([value isEqualToString:@"石"]) {
return @"金";
}
return value;
}];
//打印,不论信号发送的是什么,这一步都会走的
[siganl subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
11.过滤,未满18岁,禁止入内
- (void)demo11{
RACSignal *singal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@(15)];
[subscriber sendNext:@(17)];
[subscriber sendNext:@(21)];
[subscriber sendNext:@(14)];
[subscriber sendNext:@(30)];
[subscriber sendCompleted];
return nil;
}];
//过滤信号,打印
[[singal filter:^BOOL(NSNumber *value) {
//大于18岁的,才可以通过
return value.integerValue >= 18;//return为yes可以通过
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
12.秩序(flattenMap方法也可以换成then方法,效果一样)
-(void)demo12{
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"打蛋液");
[subscriber sendNext:@"蛋液"];
[subscriber sendCompleted];
return nil;
}];
//对信号进行秩序秩序的第一步
siganl = [siganl flattenMap:^RACStream *(NSString *value) {
//处理上一步的RACSiganl的信号value.这里的value=@"蛋液"
NSLog(@"把%@倒进锅里面煎",value);
return [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"煎蛋"];
[subscriber sendCompleted];
return nil;
}];
}];
//对信号进行第二步处理
siganl = [siganl flattenMap:^RACStream *(id value) {
NSLog(@"把%@装载盘里",value);
return [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"上菜"];
[subscriber sendCompleted];
return nil;
}];
}];
//最后打印 最后带有===上菜
[siganl subscribeNext:^(id x) {
NSLog(@"====%@",x);
}];
}
13.命令
-(void)demo13{
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
//打印:今天我投降了
//命令执行代理
NSLog(@"%@我投降了",input);
//返回一个RACSignal信号
return [RACSignal createSignal:^RACDisposable *(id subscriber) {
return nil;
}];
}];
//执行命令
[command execute:@"今天"];
}
14.延迟
- (void)demo14{
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"等等我,我还有10s就到了");
[subscriber sendNext:@"北极"];
[subscriber sendCompleted];
return nil;
}];
//延迟10s接受next的玻璃球
[[siganl delay:10] subscribeNext:^(id x) {
NSLog(@"我到了%@",x);
}];
}
15.重放
- (void)demo15{
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"电影");
[subscriber sendNext:@"电影"];
[subscriber sendCompleted];
return nil;
}];
//创建该普通信号的重复信号
RACSignal *replaySiganl = [siganl replay];
//重复接受信号
[replaySiganl subscribeNext:^(NSString *x) {
NSLog(@"小米%@",x);
}];
[replaySiganl subscribeNext:^(NSString *x) {
NSLog(@"小红%@",x);
}];
}
16.定时---每隔8小时服用一次药
- (void)demo16{
//创建定时器信号.定时8小时
RACSignal *siganl = [RACSignal interval:60 * 60 * 8 onScheduler:[RACScheduler mainThreadScheduler]];
//定时器执行代码
[siganl subscribeNext:^(id x) {
NSLog(@"吃药");
}];
}
17.超时
- (void)demo17{
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"我快到了");
RACSignal *sendSiganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}];
//发生信号要1个小时10分钟才到
[[sendSiganl delay:60 * 70] subscribeNext:^(id x) {
//这里才发送next玻璃球到siganl
[subscriber sendNext:@"我到了"];
[subscriber sendCompleted];
}];
return nil;
}];
[[siganl timeout:60 * 60 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
NSLog(@"等了你一个小时,你一直没来,我走了");
}];
}
18.重试
- (void)demo18{
__block int failedCount = 0;
//创建信号
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
if (failedCount < 100) {
failedCount ++;
NSLog(@"我失败了");
[subscriber sendError:nil];
}else{
NSLog(@"经历了数百次后,我成功了");
[subscriber sendNext:nil];
}
return nil;
}];
//重试
RACSignal *retrySiganl = [siganl retry];
//直到发生next的玻璃球
[retrySiganl subscribeNext:^(id x) {
NSLog(@"重要成功了");
}];
}
19.节流,不好意思,这里每一秒只能通过一个人,如果1s内发生多个,只通过最后一个
- (void)demo19{
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//即使发送一个next的玻璃球
[subscriber sendNext:@"A"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"B"];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"C"];
[subscriber sendNext:@"D"];
[subscriber sendNext:@"E"];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"F"];
});
return nil;
}];
//对信号进行节流,限制时间内一次只能通过一个玻璃球
[[signal throttle:1] subscribeNext:^(id x) {
NSLog(@"%@通过了",x);
}];
/*
[2015-08-16 22:08:45.677]旅客A
[2015-08-16 22:08:46.737]旅客B
[2015-08-16 22:08:47.822]旅客E
[2015-08-16 22:08:48.920]旅客F
*/
}
20.条件(takeUntil方法,当给定的signal完成前一直取值)
- (void)demo20{
RACSignal *takeSiganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//创建一个定时器信号,每一秒触发一次
RACSignal *siganl = [RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]];
[siganl subscribeNext:^(id x) {
//在这里定时发送next玻璃球
[subscriber sendNext:@"直到世界尽头"];
}];
return nil;
}];
//创建条件信号
RACSignal *conditionSiganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//设置5s后发生complete玻璃球
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"世界的今天到了,请下车");
[subscriber sendCompleted];
});
return nil;
}];
//设置条件,takeSiganl信号在conditionSignal信号接收完成前,不断取值
[[takeSiganl takeUntil:conditionSiganl] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
21.RACReplaySubject使用
/**
* RACReplaySubject创建方法
1.创建RACSubject
2.订阅信号
3.发送信号
工作流程:
1.订阅信号,内部保存了订阅者,和订阅者相应的block
2.当发送信号的,遍历订阅者,调用订阅者的nextBlock
3.发送的信号会保存起来,当订阅者订阅信号的时候,会将之前保存的信号,一个个作用于新的订阅者,保存信号的容量由capacity决定,这也是有别于RACSubject的
*/
-(void)RACReplaySubject{
RACReplaySubject *replaySubject = [RACReplaySubject subject];
[replaySubject subscribeNext:^(id x) {
NSLog(@" 1 %@",x);
}];
[replaySubject subscribeNext:^(id x) {
NSLog(@"2 %@",x);
}];
[replaySubject sendNext:@7];
[replaySubject subscribeNext:^(id x) {
NSLog(@"3 %@",x);
}];
}
22.rac_liftSelector:withSignals使用
//这里的rac_liftSelector:withSignals 就是干这件事的,它的意思是当signalA和signalB都至少sendNext过一次,接下来只要其中任意一个signal有了新的内容,doA:withB这个方法就会自动被触发
-(void)test{
RACSignal *sigalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds *NSEC_PER_SEC));
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(popTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"A"];
});
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"B"];
[subscriber sendNext:@"Another B"];
[subscriber sendCompleted];
return nil;
}];
[self rac_liftSelector:@selector(doA:withB:) withSignals:sigalA,signalB, nil];
}