項目地址:ReactiveObjC
1.鍵值觀察--監(jiān)聽TF的值發(fā)生變化
- (void)demo1{
@weakify(self);
[self.tF.rac_textSignal subscribeNext:^(NSString *value) {
@strongify(self);
self.value = value;
}];
//當self.value的值變化時調(diào)用Block,這是用KVO的機制凶赁,RAC封裝了KVO
[RACObserve(self, value) subscribeNext:^(NSString *value) {
NSLog(@"%@",value);
}];
}
2. map的使用
- (void)demo2{
//創(chuàng)建一個信號
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> 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{
//創(chuàng)建兩個通道,一個從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監(jiān)聽valueA的值的變化,過濾valueA的值,返回Yes表示通過
//只有value有值,才可通過
[[RACObserve(self, value) filter:^BOOL(id value) {
return value ? YES : NO;
}] subscribeNext:^(id x) {
NSLog(@"你向%@",x);
}];
//KVO監(jiān)聽value2的變化
[[RACObserve(self, value2) filter:^BOOL(id value) {
return value ? YES: NO;
}] subscribeNext:^(id x) {
NSLog(@"他向%@",x);
}];
//下面使value的值和value2的值發(fā)生改變
self.value = @"西";
self.value2 = @"左";
}
4.代理
/**
* RACSubject:信號提供者,自己可以充當信號,又能發(fā)送信號
創(chuàng)建方法:
1.創(chuàng)建RACSubject
2.訂閱信號
3.發(fā)送信號
工作流程:
1.訂閱信號,內(nèi)部保存了訂閱者,和訂閱者相應(yīng)block
2.當發(fā)送信號的,遍歷訂閱者,調(diào)用訂閱者的nextBolck
注:如果訂閱信號,必須在發(fā)送信號之前訂閱信號,不然收不到信號,有利用區(qū)別RACReplaySubject
*/
-(void)touchesBegan:(NSSet<UITouch *> *)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里面進行數(shù)據(jù)的傳遞
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
if (self.subject) {
[self.subject sendNext:@1];
}
}
5.廣播
//發(fā)送通知
- (void)demo5{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//發(fā)送廣播通知
[center postNotificationName:@"婦女之友" object:nil userInfo:@{@"技巧":@"用心聽"}];
}
//接收通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//RAC的通知不需要我們手動移除
//注冊廣播通知
RACSignal *siganl = [center rac_addObserverForName:@"婦女之友" object:nil];
//設(shè)置接收通知的回調(diào)處理
[siganl subscribeNext:^(NSNotification *x) {
NSLog(@"技巧: %@",x.userInfo[@"技巧"]);
}];
6.兩個信號串聯(lián),兩個管串聯(lián),一個管處理完自己的東西,下一個管才開始處理自己的東西
- (void)demo6{
//創(chuàng)建一個信號管A
RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"吃飯"];
[subscriber sendCompleted];
return nil;
}];
//創(chuàng)建一個信號管B
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"吃的飽飽的,才可以睡覺的"];
[subscriber sendCompleted];
return nil;
}];
//串聯(lián)管A和管B
RACSignal *concatSiganl = [siganlA concat:siganlB];
//串聯(lián)后的接收端處理 ,兩個事件,走兩次,第一個打印siggnalA的結(jié)果,第二次打印siganlB的結(jié)果
[concatSiganl subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
7.并聯(lián),只要有一個管有東西,就可以打印
- (void)demo7{
//創(chuàng)建信號A
RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"紙廠污水"];
[subscriber sendCompleted];
return nil;
}];
//創(chuàng)建信號B
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"電鍍廠污水"];
[subscriber sendCompleted];
return nil;
}];
//并聯(lián)兩個信號,根上面一樣,分兩次打印
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);
}];
//自己控制發(fā)生信號值
[letters sendNext:@"A"];
[letters sendNext:@"B"];
[numbers sendNext:@"1"]; //打印B1
[letters sendNext:@"C"];//打印C1
[numbers sendNext:@"2"];//打印C2
}
9.合流壓縮
- (void)demo9{
//創(chuàng)建信號A
RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"紅"];
[subscriber sendCompleted];
return nil;
}];
//創(chuàng)建信號B
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> 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<RACSubscriber> subscriber) {
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}];
//對信號進行改造,改"石"成"金"
siganl = [siganl map:^id(NSString *value) {
if ([value isEqualToString:@"石"]) {
return @"金";
}
return value;
}];
//打印,不論信號發(fā)送的是什么,這一步都會走的
[siganl subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
11.過濾,未滿18歲,禁止入內(nèi)
- (void)demo11{
RACSignal *singal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> 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<RACSubscriber> subscriber) {
NSLog(@"打蛋液");
[subscriber sendNext:@"蛋液"];
[subscriber sendCompleted];
return nil;
}];
//對信號進行秩序秩序的第一步
siganl = [siganl flattenMap:^RACStream *(NSString *value) {
//處理上一步的RACSiganl的信號value.這里的value=@"蛋液"
NSLog(@"把%@倒進鍋里面煎",value);
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"煎蛋"];
[subscriber sendCompleted];
return nil;
}];
}];
//對信號進行第二步處理
siganl = [siganl flattenMap:^RACStream *(id value) {
NSLog(@"把%@裝載盤里",value);
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"上菜"];
[subscriber sendCompleted];
return nil;
}];
}];
//最后打印 最后帶有===上菜
[siganl subscribeNext:^(id x) {
NSLog(@"====%@",x);
}];
}
13.命令
-(void)demo13{
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
//打忧:今天我投降了
//命令執(zhí)行代理
NSLog(@"%@我投降了",input);
//返回一個RACSignal信號
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
return nil;
}];
}];
//執(zhí)行命令
[command execute:@"今天"];
}
14.延遲
- (void)demo14{
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> 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<RACSubscriber> subscriber) {
NSLog(@"電影");
[subscriber sendNext:@"電影"];
[subscriber sendCompleted];
return nil;
}];
//創(chuàng)建該普通信號的重復(fù)信號
RACSignal *replaySiganl = [siganl replay];
//重復(fù)接受信號
[replaySiganl subscribeNext:^(NSString *x) {
NSLog(@"小米%@",x);
}];
[replaySiganl subscribeNext:^(NSString *x) {
NSLog(@"小紅%@",x);
}];
}
16.定時---每隔8小時服用一次藥
- (void)demo16{
//創(chuàng)建定時器信號.定時8小時
RACSignal *siganl = [RACSignal interval:60 * 60 * 8 onScheduler:[RACScheduler mainThreadScheduler]];
//定時器執(zhí)行代碼
[siganl subscribeNext:^(id x) {
NSLog(@"吃藥");
}];
}
17.超時
- (void)demo17{
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"我快到了");
RACSignal *sendSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}];
//發(fā)生信號要1個小時10分鐘才到
[[sendSiganl delay:60 * 70] subscribeNext:^(id x) {
//這里才發(fā)送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;
//創(chuàng)建信號
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
if (failedCount < 100) {
failedCount ++;
NSLog(@"我失敗了");
[subscriber sendError:nil];
}else{
NSLog(@"經(jīng)歷了數(shù)百次后,我成功了");
[subscriber sendNext:nil];
}
return nil;
}];
//重試
RACSignal *retrySiganl = [siganl retry];
//直到發(fā)生next的玻璃球
[retrySiganl subscribeNext:^(id x) {
NSLog(@"重要成功了");
}];
}
19.節(jié)流,不好意思,這里每一秒只能通過一個人,如果1s內(nèi)發(fā)生多個,只通過最后一個
- (void)demo19{
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//即使發(fā)送一個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;
}];
//對信號進行節(jié)流,限制時間內(nèi)一次只能通過一個玻璃球
[[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<RACSubscriber> subscriber) {
//創(chuàng)建一個定時器信號,每一秒觸發(fā)一次
RACSignal *siganl = [RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]];
[siganl subscribeNext:^(id x) {
//在這里定時發(fā)送next玻璃球
[subscriber sendNext:@"直到世界盡頭"];
}];
return nil;
}];
//創(chuàng)建條件信號
RACSignal *conditionSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//設(shè)置5s后發(fā)生complete玻璃球
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"世界的今天到了,請下車");
[subscriber sendCompleted];
});
return nil;
}];
//設(shè)置條件,takeSiganl信號在conditionSignal信號接收完成前,不斷取值
[[takeSiganl takeUntil:conditionSiganl] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
21.RACReplaySubject使用
/**
* RACReplaySubject創(chuàng)建方法
1.創(chuàng)建RACSubject
2.訂閱信號
3.發(fā)送信號
工作流程:
1.訂閱信號,內(nèi)部保存了訂閱者,和訂閱者相應(yīng)的block
2.當發(fā)送信號的,遍歷訂閱者,調(diào)用訂閱者的nextBlock
3.發(fā)送的信號會保存起來,當訂閱者訂閱信號的時候,會將之前保存的信號,一個個作用于新的訂閱者,保存信號的容量由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有了新的內(nèi)容玖瘸,doA:withB這個方法就會自動被觸發(fā)
-(void)test{
RACSignal *sigalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> 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<RACSubscriber> subscriber) {
[subscriber sendNext:@"B"];
[subscriber sendNext:@"Another B"];
[subscriber sendCompleted];
return nil;
}];
[self rac_liftSelector:@selector(doA:withB:) withSignals:sigalA,signalB, nil];
}