通过Cocoapods集成pod ‘ReactiveObjC’
然后在项目中导入 #import <ReactiveObjC/ReactiveObjC.h>
创建RACSignal 对象,并且发送消息
@weakify(self)
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
@strongify(self)
self.data = [[Model alloc] init];
self.data.nameStr = @"测试完成";
[subscriber sendNext:self.data];
[subscriber sendCompleted];
return nil;
}];
[signal subscribeNext:^(id _Nullable x)
{
NSLog(@"x==========%@\n",x);
}];
下面是另外一种写法
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"1"];
return [RACDisposable disposableWithBlock:^{
}];;
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"结果是========%@",x);
}];
将上面的RAC转换成flatten
RACSignal *flattenMapSignal = [signal flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
return RACObserve(self.data, nameStr);
}];
[flattenMapSignal subscribeNext:^(id _Nullable x) {
NSLog(@"结果是=========%@\n",x);
}];
创建RACSubject对象,执行完之后,就会执行rac_willDeallocSignal 方法
RACSubject *subject = [RACSubject subject];
[subject.rac_willDeallocSignal subscribeCompleted:^{
}];
[subject subscribeNext:^(id x) { //3
NSLog(@"next = %@", x);
}];
[subject sendNext:@1];
UITextField绑定textSignal 输出结果
[[_textField.rac_textSignal bind:^RACSignalBindBlock _Nullable{
return ^RACSignal *(id value,BOOL *stop){
return [RACReturnSignal return:[NSString stringWithFormat:@"输出:%@",value]];
};
}]subscribeNext:^(id _Nullable x) {
NSLog(@"结果是=====%@\n",x);
}] ;
RACReplaySubject 传的信号会重复播放
// 1.创建信号
//1.创建信号
RACReplaySubject *replaySubject = [RACReplaySubject subject];
//2.发送信号
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
//3.订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一个订阅者接收到的数据%@",x);
}];
//订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二个订阅者接收到的数据%@",x);
}];
retry 当信号出错的时候 重新执行信号操作
__block int i = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
if(i==10)
{
[subscriber sendNext:@1];
}else{
NSLog(@"接收到错误");
[subscriber sendError:nil];
}
i++;
return nil;
}] retry] subscribeNext:^(id x) {
NSLog(@"retry%@",x);
} error:^(NSError *error) {
}];
delay 延迟2s执行
RACSignal *signal = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
return nil;
}] delay:2] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
RACScheduler 定时做任务,当离开当前页面取消任务
self.disposable = [[[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"做完这件事");
[self.disposable dispose];
}];
timeout 可以让信号在一定的时间后,自动报错
RACSignal *signal = [[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
return nil;
}]timeout:1 onScheduler:[RACScheduler currentScheduler]];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"====%@\n",x);
} error:^(NSError * _Nullable error) {
//1秒后会自动调用
NSLog(@"%@",error);
}];
观察某个对象的某个值的变化,并进行过滤
[[RACObserve(self,self.data) filter:^BOOL(id _Nullable value) {
return value;
}] subscribeNext:^(Model *x) {
NSLog(@"执行了这里=======%@\n",x.nameStr);
}];
NSNotificationCenter 之观察
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"postData" object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"结果是-------%@\n",x.userInfo);
}];
监听按钮的事件
UIButton *button =[[UIButton alloc]initWithFrame:CGRectMake(50, 100, 30, 30)];
button.backgroundColor =[UIColor redColor];
[self.view addSubview:button];
[[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
}];
flattenMap 将信号包装一层发送出去
[[self.phoneTextView.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
return [RACReturnSignal return:[NSString stringWithFormat:@"输出:%@",value]];
}]subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号,把signalA拼接到signalB后,signalA发送完成,signalB才会被激活。订阅拼接的信号,不需要单独订阅signalA,signalB
注意:第一个信号必须发送完成,第二个信号才会被激活
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
return nil;
}];
RACSignal *concatSignal = [signalA concat:signalB];
[concatSignal subscribeNext:^(id x) {
NSLog(@"kl==========%@",x);
}];
then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号
then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号
注意使用then,之前信号的值会被忽略掉.
底层实现:1、先过滤掉之前的信号发出的值。2.使用concat连接then返回的信号
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@12];
return nil;
}];
}] subscribeNext:^(id x) {
// 只能接收到第二个信号的值,也就是then返回信号的值
NSLog(@"then================%@",x);
}];
merge
:把多个信号合并为一个信号,任何一个信号有新值的时候就会调用,merge:把多个信号合并成一个信号,创建多个信号
底层实现:
// 1.合并信号被订阅的时候,就会遍历所有信号,并且发出这些信号。
// 2.每发出一个信号,这个信号就会被订阅
// 3.也就是合并信号一被订阅,就会订阅里面所有的信号。
// 4.只要有一个信号被发出就会被监听。
//`merge`:把多个信号合并为一个信号,任何一个信号有新值的时候就会调用
//merge:把多个信号合并成一个信号
//创建多个信号
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
return nil;
}];
//合并信号,任何一个信号发送数据,都能监听到.
RACSignal *mergeSignal = [signalA merge:signalB];
[mergeSignal subscribeNext:^(id x) {
NSLog(@"merge==========%@\n",x);
}];
zipWith 把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元祖,才会触发压缩流的next事件
底层实现:
// 1.定义压缩信号,内部就会自动订阅signalA,signalB
// 2.每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出。
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
return nil;
}];
//压缩信号A,信号B
RACSignal *zipSignal = [signalA zipWith:signalB];
[zipSignal subscribeNext:^(RACTwoTuple *x)
{
NSLog(@"zipWith============%@,%@\n\n",x.first,x.second);
}];
combineLatest 将多个信号合并起来,并且拿到各个信号的最新的值,
// 底层实现:
// 1.当组合信号被订阅,内部会自动订阅signalA,signalB,必须两个信号都发出内容,才会被触发。
// 2.并且把两个信号组合成元组发出。
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@5];
return nil;
}];
// 把两个信号组合成一个信号,跟zip一样,没什么区别
RACSignal *combineSignal = [signalA combineLatestWith:signalB];
[combineSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
reduce
聚合:用于信号发出的内容是元组,把信号发出元组的值聚合成一个值,聚合
常见的用法,(先组合在聚合)。combineLatest:(id)signals reduce:(id (^)())reduceBlock
// reduce中的block简介:
// reduceblcok中的参数,有多少信号组合,reduceblcok就有多少参数,每个参数就是之前信号发出的内容
// reduceblcok的返回值:聚合信号之后的内容。
底层实现:订阅聚合信号,每次有内容发出,就会执行reduceblcok,把信号内容转换成reduceblcok返回的值
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber)
{
[subscriber sendNext:@8];
return nil;
}];
RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber *num1 ,NSNumber *num2){
return [NSString stringWithFormat:@"%@ %@",num1,num2];
}];
[reduceSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
filter:过滤信号,使用它可以获取满足条件的信号. 每次信号发出,会先执行过滤条件判断
[_textField.rac_textSignal filter:^BOOL(NSString *value) {
return value.length > 3;
}];
ignore:忽略完某些值的信号.
[[_phoneTextView.rac_textSignal ignore:@"1"] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
distinctUntilChanged:当上一次的值和当前的值有明显的变化就会发出信号,否则会被忽略掉。
// 过滤,当上一次和当前的值不一样,就会发出内容。
// 在开发中,刷新UI经常使用,只有两次数据不一样才需要刷新
[[_phoneTextView.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
take:从开始一共取N次的信号 1、创建信号
// RACSubject *signal = [RACSubject subject];
//
// // 2、处理信号,订阅信号
// [[signal take:3] subscribeNext:^(id x) {
//
// NSLog(@"%@",x);
// }];
//
// // 3.发送信号
// [signal sendNext:@1];
//
// [signal sendNext:@6];
// [signal sendNext:@61];
// takeLast:取最后N次的信号,前提条件,订阅者必须调用完成,因为只有完成,就知道总共有多少信号.
// 1、创建信号
// RACSubject *signal = [RACSubject subject];
//
// // 2、处理信号,订阅信号
// [[signal takeLast:1] subscribeNext:^(id x) {
//
// NSLog(@"%@",x);
// }];
//
// // 3.发送信号
// [signal sendNext:@1];
//
// [signal sendNext:@2];
//[signal sendNext:@232];
// [signal sendCompleted];
// takeUntil:(RACSignal *):获取信号直到某个信号执行完成
takeUntil 当当前对象被销毁时,停止执行
[_textField.rac_textSignal takeUntil:self.rac_willDeallocSignal];
skip:(NSUInteger):跳过几个信号,不接受
[_phoneTextView.rac_textSignal skip:1] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
switchToLatest 用于signalOfSignals(信号的信号),有时候信号也会发出信号,会在signalOfSignals中,获取signalOfSignals发送的最新信号。
RACSubject *signalOfSignals = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
// 获取信号中信号最近发出信号,订阅最近发出的信号。
// 注意switchToLatest:只能用于信号中的信号
[signalOfSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[signalOfSignals sendNext:signal];
[signal sendNext:@1];
ReactiveCocoa操作方法之秩序。
doNext: 执行Next之前,会先执行这个Block
doCompleted: 执行sendCompleted之前,会先执行这个Block
[[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] doNext:^(id x) {
// 执行[subscriber sendNext:@1];之前会调用这个Block
NSLog(@"doNext");;
}] doCompleted:^{
// 执行[subscriber sendCompleted];之前会调用这个Block
NSLog(@"doCompleted");;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
ReactiveCocoa操作方法之线程
deliverOn: 内容传递切换到制定线程中,副作用在原来线程中,把在创建信号时block中的代码称之为副作用
subscribeOn: 内容传递和副作用都会切换到制定线程中。
数组操作
Array *numbers = @[@1,@2,@3,@4];
[numbers.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"数据=======%@\n",x);
}];
字典操作
NSDictionary *dict = @{@"name":@"xmg",@"age":@10};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
RACTupleUnpack(NSString *key,NSString *value) = x;
NSLog(@"===%@",key);
NSLog(@"=====%@",value);
}];
map 映射成新的数据
NSArray *numbers = @[@1,@2,@3,@4];
NSArray *numbers2 = [[numbers.rac_sequence map:^id _Nullable(id _Nullable value) {
return value;
}]array] ;
RACCommand 命令执行
mand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"请求数据"];
[subscriber sendCompleted];
return nil;
}];
}];
self.command = command;
// self.btnClick.rac_command = command;
// [self.btnClick.rac_command.executionSignals subscribeNext:^(RACSignal<id> * _Nullable x) {
//
// NSLog(@"===%@\n",x);
//
// [x subscribeNext:^(id _Nullable x) {
//
// NSLog(@"2222===%@\n",x);
//
// }];
// }];
[self.command.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"4444===%@\n",x);
}];
[[command.executing skip:1] subscribeNext:^(id x) {
//
// if ([x boolValue] == YES) {
// // 正在执行
// NSLog(@"正在执行");
//
// }else{
// // 执行完成
// NSLog(@"执行完成");
// }
//
// }];
[self.command execute:@1];
1.代替代理
// 需求:自定义redView,监听红色view中按钮点击
// 之前都是需要通过代理监听,给红色View添加一个代理属性,点击按钮的时候,通知代理做事情
// rac_signalForSelector:把调用某个对象的方法的信息转换成信号,就要调用这个方法,就会发送信号。
// 这里表示只要redV调用btnClick:,就会发出信号,订阅就好了。
[[redV rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
// NSLog(@"点击红色按钮");
// }];
// 2.KVO
// // 把监听redV的center属性改变转换成信号,只要值改变就会发送信号
// // observer:可以传入nil
// [[redV rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
//
// NSLog(@"%@",x);
//
// }];
// // 把按钮点击事件转换为信号,点击按钮,就会发送信号
// [[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
//
// NSLog(@"按钮被点击了");
// }];
//
// // 4.代替通知
// // 把监听到的通知转换信号
// [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
// NSLog(@"键盘弹出");
// }];
// // 6.处理多个请求,都返回结果的时候,统一做处理.
// RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//
// // 发送请求1
// [subscriber sendNext:@"发送请求1"];
// return nil;
// }];
//
// RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// // 发送请求2
// [subscriber sendNext:@"发送请求2"];
// return nil;
// }];
//
// // 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。
// [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];
属性绑定
RAC(self.labelView,text) = _textField.rac_textSignal;
[RACObserve(self.view, center) subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
将数据包装成元祖
RACTuple *tuple = RACTuplePack(@10,@20);
TupleUnpack(NSString *number) = tuple;
[[[tuple.rac_sequence map:^id _Nullable(id _Nullable value) {
return value;
}]signal]subscribeNext:^(id _Nullable x) {
NSLog(@"number============%@\n",x);
}];
throttle 节流,当某个信号发送比较频繁的时候,可以使用节流
// 节流:当某个信号发送比较频繁时,可以使用节流,在某一段时间不发送信号内容,过了一段时间获取信号的最新内容发出。
// RACSubject *subject = [RACSubject subject];
// // 节流1秒,1秒后接收最后一个发送的信号
// [[subject throttle:1] subscribeNext:^(id x) {
// NSLog(@"%@", x);
// }];
// [subject sendNext:@1];
// [subject sendNext:@2];
// [subject sendNext:@3];