1、RACSignal
// 只要订阅者调用sendNext,就会执行nextBlock
// 只要订阅RACDynamicSignal,就会执行didSubscribe
// 前提条件是RACDynamicSignal,不同类型信号的订阅,处理订阅的事情不一样
//创建信号,此时信号是冷信号,并不能发送数据RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"发送数据"];
//信号销毁
return[RACDisposable disposableWithBlock:^{
NSLog(@"信号取消订阅");
}];
}];
//信号订阅,此时信号变为热信号,接收到数据[signal subscribeNext:^(id x) {
// nextBlock调用:只要订阅者发送数据就会调用
NSLog(@"%@", x);
}];
2、RACSubject
//创建信号RACSubject *subject = [RACSubject subject];
/* 不同信号订阅的方式不一样
RACSubject处理订阅:仅仅是保存订阅者,可以多个订阅者
底层实现:遍历所有的订阅者,调用nextBlock
执行流程:
RACSubject被订阅,仅仅是保存订阅者
RACSubject发送数据,遍历所有的订阅,调用他们的nextBlock
*/ [subject subscribeNext:^(id x) {
NSLog(@"++++++%@", x);
}];
[subject subscribeNext:^(id x) {
NSLog(@"-----%@", x);
}];
[subject sendNext:@111];
3、RACReplaySubject
//创建信号RACReplaySubject *replaySubject = [RACReplaySubject subject];//可以先发送数据再订阅信号[replaySubject sendNext:@111111];
[replaySubject subscribeNext:^(id x) {
NSLog(@"---%@", x);
}];
[replaySubject subscribeNext:^(id x) {
NSLog(@"+++++%@", x);
}];
4、RAC中的KVO、通知、监听事件、监听文本框、计时器
//KVO
//方式一:其中_redView是属性UIView,监听frame变化
[_redView rac_observeKeyPath:@"frame"options:NSKeyValueObservingOptionNew observer:nil block:^(idvalue, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {//value就是frame变化之后的值NSLog(@"----%@", value); }];
//方式二:[[_redView rac_valuesForKeyPath:
@"frame"observer:nil] subscribeNext:^(id x) {
NSLog(@"+++++%@", x);
}];//监听事件,监听按钮的点击事件[[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
NSLog(@"控制器按钮被点击"); }];
//_label增加点击手势,监听点击事件UITapGestureRecognizer
*tap = [[UITapGestureRecognizer alloc]init];
[[tap rac_gestureSignal] subscribeNext:^(UITapGestureRecognizer *x) {
NSLog(@"----label增加单击手势%@", x);
}];
[_label addGestureRecognizer:tap];
//通知,监听键盘弹起的通知[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotificationobject:nil] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
//监听文本框,只要文本框中内容一产生变化,就会走这个block[_textField.rac_textSignal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[[_textField rac_signalForControlEvents:UIControlEventEditingDidEndOnExit] subscribeNext:^(id x) {
//return之后隐藏键盘
//x是TextFieldNSLog(@"%@",x);
}];
//延迟一定时间做某事[[RACScheduler mainThreadScheduler]afterDelay:2.0fschedule:^{
NSLog(@"2秒之后发生的事情");
}];
// 每个一定长度时间做一件事,类似NSTimer[[RACSignal interval:1onScheduler:[RACScheduler mainThreadScheduler]]subscribeNext:^(NSDate * date) {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
_label.text = [formatter stringFromDate:date];
// NSLog(@"%@",[formatter stringFromDate:date]);}];
//监听UIAlertView弹框的点击事件UIAlertView
* alertView = [[UIAlertView alloc]initWithTitle:@"警告"message:@"是否确认登录?"delegate:self cancelButtonTitle:@"取消"otherButtonTitles:@"确定", nil];
//实现alertView的点击事件的delegate方法[[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:
@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple *tuple) { //点击取消、确定按钮会到本blockRACTupleUnpack(UIAlertView*alert, NSNumber *index) = tuple;
NSLog(@"alertView : %@------%@",alert, index); }]; [alertView show]; //类似UIAlertViewUIActionSheet*sheet = [[UIActionSheet alloc]initWithTitle:nildelegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"相机", @"相册", nil];
[[self rac_signalForSelector:@selector(actionSheet:clickedButtonAtIndex:) fromProtocol:@protocol(UIActionSheetDelegate)] subscribeNext:^(RACTuple * tuple) {
RACTupleUnpack(UIActionSheet *alert, NSNumber *index) = tuple;
NSLog(@"alertView : %@------%@",alert, index);
}];
[sheet showInView:self.view];
5、RAC中的集合:
//类似NSArray
RACTuple *tuple = [RACTuple tupleWithObjectsFromArray:@[@1,@"dssds", @3]];
NSNumber *first = tuple[0];
NSLog(@"%@", first);
//arrayNSArray *array = @[@"123",@"456",@"789"];
//RAC集合RACSequence *sequence = array.rac_sequence;
//转化为信号RACSignal *signal = sequence.signal;
[signal subscribeNext:^(id x) {
NSLog(@"%@", x); }];
//联合起来遍历数据就是:[array.rac_sequence.signal subscribeNext:
^(id x) {
NSLog(@"------%@", x);
}];
//DictNSDictionary *dict = @{@"name":@"小明",@"age":@"20"};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
// NSString *key = x[0];
// NSString *value = x[1];
// NSLog(@"key : %@, value : %@", key, value);
// RACTupleUnpack:用来解析元组
// 宏里面的参数,传需要解析出来的变量名
// = 右边,放需要解析的元组RACTupleUnpack(NSString *key, NSString *value) = x;
NSLog(@"%@--%@", key, value);
}];
NSArray *allModels = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil]];
// NSMutableArray *models = [NSMutableArray array];
// [allModels.rac_sequence.signal subscribeNext:^(NSDictionary *x) {
//// FlagModel *model = [FlagModel flagWithDict:x];
// [models addObject:model];
////}];
//models数组中的数据是已经将数据转好的模型数据NSArray *models = [[allModels.rac_sequence map:^id(idvalue) {
//字典转模型
return [FlagModel flagWithDict:value];
}] array];
NSLog(@"-----%@", models);
6、RACMulticastConnection
//弊端:有几个订阅者就会请求几次数据
// 1.创建信号RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"发送热门模块的请求");
// 3.发送数据[subscriber sendNext:@1];
return nil;
}];
// 2.订阅信号[signal subscribeNext:^(id x) {
NSLog(@"订阅者一%@",x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"订阅者二%@",x);
}];
//弊端优化
// 不管订阅多少次信号,就会请求一次
// RACMulticastConnection:必须要有信号
// 1.创建信号RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// didSubscribe什么时候来:连接类连接的时候NSLog(@"发送热门模块的请求");
[subscriber sendNext:@"热门模块的数据"];
return nil;
}];
// 2.把信号转换成连接类
// 确定源信号的订阅者RACSubject
// RACMulticastConnection *connection = [signal publish];RACMulticastConnection *connection = [signal2 multicast:[RACReplaySubject subject]];
// 3.订阅连接类信号[connection.signal subscribeNext:^(id x) {
// nextBlock:发送数据就会来NSLog(@"订阅者1:%@",x);
}];
// 4.连接 [connection connect];
7、RACCommand
//创建RACCommand,RACCommand命令在RAC很常用,常用语网络请求
RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal *(id input) {
NSLog(@"---input = %@", input);
//11return[RACSignal createSignal:^RACDisposable *(idsubscriber) {
//网络请求,将请求的数据发送出去[subscriber sendNext:
@"网络请求的数据"];
return nil;
}];
}];
//取到command创建的RACSignal
//方式一:RACSignal *signal = [command execute:@1];
[signal subscribeNext:^(id x) {
NSLog(@"---%@", x);
}];
//方式2:
// 注意:必须要在执行命令前,订阅
// executionSignals:信号源,信号中信号,signalOfSignals:信号:发送数据就是信号[command.executionSignals subscribeNext:^(RACSignal *x) {
NSLog(@"%@", x);
[x subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
}];
//方式3: switchToLatest获取最新发送的信号,只能用于信号中信号[command.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"--x = %@", x);
}];
[command execute:@23];
//下面对信号中的信号讲解:
// 创建信号中信号RACSubject *signalOfSignals = [RACSubject subject];
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
// 订阅信号
// [signalOfSignals subscribeNext:^(RACSignal *x) {
// [x subscribeNext:^(id x) {
// NSLog(@"%@",x);
// }];
// }];
// switchToLatest:获取信号中信号发送的最新信号[signalOfSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 发送信号 [signalOfSignals sendNext:signalA];
[signalA sendNext:@1];
[signalB sendNext:@"BB"];
[signalA sendNext:@"11"];
//**********************************************************************************************************************
// 当前命令内部发送数据完成,一定要主动发送完成
// 1.创建命令RACCommand *command2 = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
// input:执行命令传入参数
// Block调用:执行命令的时候就会调用NSLog(@"%@",input);
return[RACSignal createSignal:^RACDisposable *(id subscriber) {
// 发送数据[subscriber sendNext:@"执行命令产生的数据"];
// 发送完成 [subscriber sendCompleted];
return nil;
}];
}];
// 监听事件有没有完成[command2.executing subscribeNext:^(id x) {
if([x boolValue] == YES) {// 当前正在执行NSLog(@"当前正在执行");
}else{
// 执行完成/没有执行NSLog(@"执行完成/没有执行");
}
}];
// 2.执行命令[command2 execute:@1];
8、bind,信号的绑定
// 1.创建信号RACSubject *subject = [RACSubject subject];
// 2.绑定信号RACSignal *bindSignal = [subject bind:^RACStreamBindBlock{
// block调用时刻:只要绑定信号被订阅就会调用return^RACSignal *(idvalue, BOOL *stop){
// block调用:只要源信号发送数据,就会调用block
// block作用:处理源信号内容
// value:源信号发送的内容
NSLog(@"接收到原信号的内容:%@",value);
value = [NSString stringWithFormat:@"xmg:%@",value];
// 返回信号,不能传nil,返回空信号[RACSignal empty]return[RACReturnSignalreturn:value];
};
}];
// 3.订阅绑定信号[bindSignal subscribeNext:^(id x) {
// blcok:当处理完信号发送数据的时候,就会调用这个BlockNSLog(@"接收到绑定信号处理完的信号%@",x);
}];
// 4.发送数据[subject sendNext:@"123"];
9、map、flattenMap
//map、flattenMap主要是对发送的数据进行编辑,如:可以将网络请求的数据转化的模型在发送
// 创建信号,RACSubject *subject2 = [RACSubject subject];
// 绑定信号RACSignal *bindSignal2 = [subject2 map:^id(id value) {
// 返回的类型,就是你需要映射的值return[NSString stringWithFormat:@"请求的数据:%@",value];
}];
// 订阅绑定信号[bindSignal2 subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subject2 sendNext:@"123"];//******************flattenMap一般用于信号中的信号*******************************RACSubject *signalOfsignals = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
[[signalOfsignals flattenMap:^RACStream *(id value) {
return value;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 发送信号 [signalOfsignals sendNext:signal];
[signal sendNext:@"213"];
10、组合
// 组合,两个信号都完成才执行
// concat:皇上,皇太子
// 创建信号ARACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 发送请求NSLog(@"发送上部分请求");
// 发送信号[subscriber sendNext:@"上部分数据"];
[subscriber sendCompleted];
return nil;
}];
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 发送请求NSLog(@"发送下部分请求");
// 发送信号[subscriber sendNext:@"下部分数据"];
return nil;
}];
// concat:按顺序去连接
// 注意:concat,第一个信号必须要调用sendCompleted
// 创建组合信号RACSignal *concatSignal = [siganlA concat:siganlB];
// 订阅组合信号[concatSignal subscribeNext:^(id x) {
// 既能拿到A信号的值,又能拿到B信号的值NSLog(@"%@",x);
}];
//***************************************************************************************************
// 创建信号ARACSignal *siganl1 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 发送请求NSLog(@"发送上部分请求");
// 发送信号[subscriber sendNext:@"上部分数据"];
// 发送完成 [subscriber sendCompleted];
return nil;
}];
// 创建信号BRACSignal *siganl2 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 发送请求NSLog(@"发送下部分请求");
// 发送信号[subscriber sendNext:@"下部分数据"];
return nil;
}];
// 创建组合信号
// then:忽悠掉第一个信号所有值RACSignal *thenSiganl = [siganl1 then:^RACSignal *{
// 返回信号就是需要组合的信号return siganl2;
}];
// 订阅信号[thenSiganl subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//***************************************************************************************************
// 创建信号ARACSubject *signalA = [RACSubject subject];
// 创建信号BRACSubject *signalB = [RACSubject subject];
// 组合信号RACSignal *mergeSiganl = [signalA merge:signalB];
// 订阅信号[mergeSiganl subscribeNext:^(id x) {
// 任意一个信号发送内容都会来这个blockNSLog(@"%@",x);
}];
// 发送数据[signalB sendNext:@"下部分"];
[signalA sendNext:@"上部分"];
//***************************************************************************************************
// zipWith:夫妻关系
// 创建信号ARACSubject *signalC = [RACSubject subject];
// 创建信号BRACSubject *signalD = [RACSubject subject];
// 压缩成一个信号
// zipWith:当一个界面多个请求的时候,要等所有请求完成才能更新UI
// zipWith:等所有信号都发送内容的时候才会调用RACSignal *zipSignal = [signalC zipWith:signalD];
// 订阅信号[zipSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 发送信号[signalD sendNext:@2];
[signalC sendNext:@1];
//***************************************************************************************************
// 组合
// 组合哪些信号
// reduce:聚合
// reduceBlock参数:根组合的信号有关,一一对应RACSignal *comineSiganl = [RACSignal combineLatest:@[_accountFiled.rac_textSignal,_pwdField.rac_textSignal] reduce:^id(NSString *account,NSString *pwd){
// block:只要源信号发送内容就会调用,组合成新一个值NSLog(@"%@ %@",account,pwd);
// 聚合的值就是组合信号的内容return@(account.length && pwd.length);
}];
// 订阅组合信号
// [comineSiganl subscribeNext:^(id x) {
// _loginBtn.enabled = [x boolValue];
// }];
RAC(_loginBtn,enabled) = comineSiganl;
11、过滤
// 只有当我们文本框的内容长度大于5,才想要获取文本框的内容[[_textField.rac_textSignal filter:^BOOL(id value) {
// value:源信号的内容return[value length] >5;
// 返回值,就是过滤条件,只有满足这个条件,才能能获取到内容
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//***************************************************************************************************
// ignore:忽略一些值
// ignoreValues:忽略所有的值
// 1.创建信号RACSubject *subject = [RACSubject subject];
// 2.忽略一些RACSignal *ignoreSignal = [subject ignoreValues];
// 3.订阅信号[ignoreSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 4.发送数据[subject sendNext:@"13"];
[subject sendNext:@"2"];
[subject sendNext:@"44"];
//***************************************************************************************************
// 1.创建信号RACSubject *subject2 = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
// take:取前面几个值
// takeLast:取后面多少个值.必须要发送完成
// takeUntil:只要传入信号发送完成或者发送任意数据,就不能在接收源信号的内容[[subject2 takeUntil:signal] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subject2 sendNext:@"1"];
// [signal sendNext:@1];
// [signal sendCompleted]; [signal sendError:nil];
[subject2 sendNext:@"2"];
[subject2 sendNext:@"3"];
//***************************************************************************************************
// distinctUntilChanged:如果当前的值跟上一个值相同,就不会被订阅到
// 1.创建信号RACSubject *subject3 = [RACSubject subject];
[[subject3 distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subject3 sendNext:@"1"];
[subject3 sendNext:@"2"];
[subject3 sendNext:@"2"];
//***************************************************************************************************
// skip;跳跃几个值
// 1.创建信号RACSubject *subject4 = [RACSubject subject];
[[subject4 skip:2] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subject4 sendNext:@"1"];
[subject4 sendNext:@"2"];
[subject4 sendNext:@"3"];
12、RAC其他一些操作
//******************************************** [[[[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside]
doNext:^(id x) {
[self.btn setTitle:@"你好" forState:UIControlStateNormal];
}]
map:^id(id value) {
return @(YES);
}]
subscribeNext:^(NSNumber *x) {
self.btn.backgroundColor = x ? [UIColor orangeColor] : [UIColor cyanColor];
}];
//**************************************************************
//doNext: 执行Next之前,会先执行这个Block
//doCompleted: 执行sendCompleted之前,会先执行这个Block
[[[[RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] doNext:^(id x) {
// 执行[subscriber sendNext:@1];之前会调用这个BlockNSLog(@"doNext");;
}] doCompleted:^{
// 执行[subscriber sendCompleted];之前会调用这个BlockNSLog(@"doCompleted");;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//*********************************************************
//timeout:超时,可以让一个信号在一定的时间后,自动报错。
RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id subscriber) {
return nil;
}] timeout:1 onScheduler:[RACScheduler currentScheduler]];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
} error:^(NSError *error) {
// 1秒后会自动调用NSLog(@"%@",error);
}];
//interval 定时:每隔一段时间发出信号[[RACSignal interval:1onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//delay 延迟发送next。[[[RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@1];
return nil;
}] delay:2] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//*********************************************************
//retry重试 :只要失败,就会重新执行创建信号中的block,直到成功.__blockinti =0;
[[[RACSignal createSignal:^RACDisposable *(id subscriber) {
if(i ==10) {
[subscriber sendNext:@1];
}else{
NSLog(@"接收到错误");
[subscriber sendError:nil];
}
i++;
return nil;
}] retry] subscribeNext:^(id x) {
NSLog(@"%@",x);
} error:^(NSError *error) {
}];
//*********************************************************
//replay重放:当一个信号被多次订阅,反复播放内容RACSignal *signal3 = [[RACSignal createSignal:^RACDisposable* (id subscriber) {
[subscriber sendNext:@1];
[subscriber sendNext:@2];
return nil;
}] replay];
[signal3 subscribeNext:^(id x) {
NSLog(@"第一个订阅者%@",x);
}];
[signal3 subscribeNext:^(id x) {
NSLog(@"第二个订阅者%@",x);
}];
//*********************************************************
//throttle节流:当某个信号发送比较频繁时,可以使用节流,在某一段时间不发送信号内容,过了一段时间获取信号的最新内容发出。RACSubject *signal4 = [RACSubject subject];
// _signal = signal;
// 节流,在一定时间(1秒)内,不接收任何信号内容,过了这个时间(1秒)获取最后发送的信号内容发出。[[signal4 throttle:1] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
13、RAC中常用的宏:
//1、防止循环引用,类似__weak typeof(self)waekSelf = self; @weakify(self)
[_textField.rac_textSignal subscribeNext:^(NSString *x) {
@strongify(self)
self.textField.text = x;
}];//2、包装元组RACTuple *tuple = RACTuplePack(@1, @2);
NSLog(@"---%@", tuple[0]);
//之前赋值方式// [_textField.rac_textSignal subscribeNext:^(id x) {//// _label.text = x;//// }];
// 用来给某个对象的某个属性绑定信号,只要产生信号内容,就会把内容给属性赋值RAC(_label, text) = _textField.rac_textSignal;