RAC的定义
ReactiveCocoa(简称:RAC),其具有函数式编程和响应式编程的特性,是github开源的一套开源框架
RAC的作用
- 解决开发中状态与状态之间的过多依赖
- 解决MVC中Controller过于臃肿的问题
- 提供统一的消息传递机制
- 使代码高聚合,方便管理
RAC的编程思想
函数响应式编程(FRP)框架、将一切转换为信号
注意:RAC通过weakify、strongify解决循环引用问题
RAC的API
集合类型的遍历
-(void)rac_sequence {
NSArray *array = @[@"111",@"222",@"333"];
//遍历数组
[array.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"rac_array__%@",x);
}];
NSDictionary *dict = @{@"name":@"lmf",@"age":@"18"};
[dict.rac_sequence.signal subscribeNext:^(id _Nullable x) {
//Tuple:元祖
//使用方式类似Array
RACTwoTuple *tuple = x;
NSLog(@"rac_dict__%@:%@",tuple[0],tuple[1]);
}];
}
timer
- (void)rac_timer {
[[RACSignal interval:1 onScheduler: [RACScheduler schedulerWithPriority:(RACSchedulerPriorityHigh) name:@"com.lmf.rac_timer"]] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"rac_timer______%@",x);
}];
}
基础UI&&手势
- (void)rac_ui {
//button
[[self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"rac_button1:%@",x);
}];
self.button.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
NSLog(@"rac_button2:%@",input);
return [RACSignal empty];
}];
//textField
[self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
NSLog(@"rac_textField:%@", x);
}];
//tap
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]init];
self.label.userInteractionEnabled = YES;
[self.label addGestureRecognizer:tap];
[tap.rac_gestureSignal subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
NSLog(@"rac_tap:%@",x);
}];
}
通知
- (void)rac_notify {
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"rac_notification:%@", x);
}];
}
代理
- (void)rac_delegate {
self.textField.delegate = self;
[[self rac_signalForSelector:@selector(textFieldDidBeginEditing:) fromProtocol:@protocol(UITextFieldDelegate)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"rac_delegate:%@",x);
}];
}
KVO
- (void)rac_kvo {
[RACObserve(self, name) subscribeNext:^(id _Nullable x) {
NSLog(@"rac_kvo:%@",x);
}];
self.name = @"lmf";
}
RAC
把一个对象的某个属性绑定一个信号,只要发出信号,就会把信号的内容给对象的属性赋值
- (void)rac_rac {
RAC(self.label, text) = self.textField.rac_textSignal;
/*
//等同于
[self.textField.rac_textSignal subscribeNext:^(id x) {
self.label.text = x;
}];
*/
}
signal
- (void)rac_signal {
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
NSLog(@"createSignal");
[subscriber sendNext:@"发送信号"];
[subscriber sendError:[NSError errorWithDomain:@"baidu" code:404 userInfo:nil]];
return [RACDisposable disposableWithBlock:^{
NSLog(@"销毁了");
}];
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext:%@",x);
}];
[signal subscribeError:^(NSError * _Nullable error) {
NSLog(@"subscribeError:%@", error);
}];
}
retry
只要任务失败就会重新执行创建信号中的block的,直到成功
- (void)rac_retry {
__block int num = 0;
[[[RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
if (num == 10) {
[subscriber sendNext:@10];
}else {
num ++;
[subscriber sendError:[NSError errorWithDomain:@"baidu" code:-1 userInfo:nil]];
}
return nil;
}] retry] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_retry_next:%@",x);
} error:^(NSError * _Nullable error) {
NSLog(@"rac_retry_error:%@",error);
}];
}
信号超时处理
- (void)rac_timeout {
RACSignal *signal = [[RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
return nil;
}] timeout:1 onScheduler:[RACScheduler currentScheduler]];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"rac_timeout_subscribeNext:%@",x);
} error:^(NSError * _Nullable error) {
//超时会执行这段代码
NSLog(@"rac_timeout_error:%@",error);
}];
}
switchToLastest
只能用于信号中的信号;获取信号中信号最近发出信号,订阅最近发出的信号
- (void)rac_switchToLastest {
RACSubject *signalOfSignals = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
RACSubject *signal2 = [RACSubject subject];
[signalOfSignals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"rac_switchToLastest:%@",x);
}];
[signalOfSignals sendNext:signal2];
[signalOfSignals sendNext:signal];
[signal sendNext:@"hahaha"];
[signal2 sendNext:@"12345"];
}
takeUntil
当takeUntil传入的信号发出信号或者sendCompleted后,源信号将不再接受信号消息
- (void)rac_takeUntil {
RACSubject *subject = [RACSubject subject];
RACSubject *subject2 = [RACSubject subject];
[[subject takeUntil:subject2] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_takeUntil:%@",x);
}];
[subject sendNext:@1];
[subject sendNext:@2];
// [subject2 sendNext:@3];
[subject2 sendCompleted];
[subject sendNext:@4];
[subject2 sendNext:@5];
[subject sendNext:@6];
}
take&&takeLast
take和takeLast使用方式一样,take取前x个信号,takeLast取后x个信号,takeLast使用后需要使用sendCompleted,告诉takeLast发送完成
- (void)rac_takeLast {
RACSubject *subject = [RACSubject subject];
[[subject takeLast:2] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_takeLast:%@",x);
}];
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
[subject sendCompleted];
}
skip
跳过前x个信号
- (void)rac_skip {
[[self.textField.rac_textSignal skip:1] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"rac_skip:%@",x);
}];
}
distinctUntilChanged
两次内容不一致就会发出信号,否则被忽略
- (void)rac_distinctUntilChanged {
RACSubject *subject = [RACSubject subject];
[[subject distinctUntilChanged] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_distinctUntilChanged:%@",x);
}];
[subject sendNext:@1];
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@2];
}
ignore
忽略传入的信号
- (void)rac_ignore {
// [[self.textField.rac_textSignal ignore:@"2"] subscribeNext:^(NSString * _Nullable x) {
// NSLog(@"rac_ignore:%@",x);
// }];
RACSubject *subject = [RACSubject subject];
[[subject ignore:@2] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_ignore:%@",x);
}];
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
}
filter
在发送信号前,先执行过滤条件,返回true,在发送信号
- (void)rac_filter {
RACSubject *subject = [RACSubject subject];
[[subject filter:^BOOL(id _Nullable value) {
NSString *str = value;
return str.length > 6;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_filter:%@",x);
}];
[subject sendNext:@"1"];
[subject sendNext:@"22"];
[subject sendNext:@"666666"];
[subject sendNext:@"7777777"];
}
reduce
信号组合后,每次有信号发出,先执行block进行组合,再发送信号
reduce block注意事项:
参数:有多少信号组合,block就有多少个参数,每个参数就是之前信号发出的内容
返回值:组合后的内容
- (void)rac_reduce {
RACSignal *signal1 = self.textField.rac_textSignal;
RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
RACSignal *reduceSignal = [RACSignal combineLatest:@[signal1, signal2] reduce:^(id value1, id value2){
return [NSString stringWithFormat:@"组合reduce == 1:%@ 2:%@", value1, value2];
}];
[reduceSignal subscribeNext:^(id _Nullable x) {
NSLog(@"rac_reduce:%@",x);
}];
}
combineLatestWith
当组合信号被订阅,内部会自动订阅多个信号,必须多个信号都被触发才会触发合并信号,并会把多个信号的值组合成元祖返回
- (void)rac_combineLast {
RACSignal *signal1 = self.textField.rac_textSignal;
RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
RACSignal *comSignal = [signal1 combineLatestWith:signal2];
[comSignal subscribeNext:^(id _Nullable x) {
NSLog(@"rac_combineLast:%@",x);
}];
}
zip(不太明白)
每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出
- (void)rac_zip {
RACSignal *signal1 = self.textField.rac_textSignal;
RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
RACSignal *zipSignal = [signal1 zipWith:signal2];
[zipSignal subscribeNext:^(id _Nullable x) {
NSLog(@"rac_zip:%@",x);
}];
}
merge
把多个信号合并成一个信号,任何一个信号发送数据,都可以监听到
- (void)rac_merge {
RACSignal *signal1 = self.textField.rac_textSignal;
RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
RACSignal *mergeSignal = [signal1 merge:signal2];
[mergeSignal subscribeNext:^(id _Nullable x) {
NSLog(@"rac_merge:%@",x);
}];
}
then
第一个信号必须执行sendCompleted 第二个信号才会触发,监听的是第二个信号的值
- (void)rac_then {
[[[RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
// [subscriber sendNext:@(123)];
[subscriber sendCompleted];
return nil;
}] then:^RACSignal * _Nonnull{
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@(456)];
[subscriber sendCompleted];
return nil;
}];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_then:%@",x);
}];
}
contact
先监听前一个信号,再监听后面的信号
- (void)rac_contact {
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@(123)];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@(456)];
[subscriber sendCompleted];
return nil;
}];
RACSignal *contactSignal = [signal1 concat:signal2];
[contactSignal subscribeNext:^(id _Nullable x) {
NSLog(@"rac_contact:%@",x);
}];
}
bind
需要单独导入RACReturnSignal.h
- (void)rac_bind {
[[self.textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{
return ^RACSignal *(id value, BOOL *sotp) {
return [RACReturnSignal return:[NSString stringWithFormat:@"输出结果%@", value]];
};
}] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_bind:%@",x);
}];
}
map
将源信息做了处理
- (void)rac_map {
[[self.textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
return [NSString stringWithFormat:@"nb_%@",value];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_map:%@",x);
}];
}
flattenMap
作用好像和map类似 都是对源信号进行了转换
- (void)rac_flattenMap {
[[self.textField.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
return [RACReturnSignal return:[NSString stringWithFormat:@"输出结果:%@",value]];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"rac_flattenMap:%@",x);
}];
}
RACMulticastConnection
当有多个订阅者时,按传统写法会发送多次信号,这时我们可以通过RACMulticatConnection,来解决
- (void) rac_multicastConnection {
/*
// 普通写法, 这样的缺点是:每订阅一次信号就得重新创建并发送请求
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 发送信号
[subscriber sendNext:@"我是信号"];
return nil;
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
*/
// 比较好的做法:使用RACMulticastConnection,无论订阅多少次,只发送一次
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 发送信号
[subscriber sendNext:@"我是信号"];
return nil;
}];
RACMulticastConnection *connection = [signal publish];
[connection.signal subscribeNext:^(id x) {
NSLog(@"1:%@", x);
}];
[connection.signal subscribeNext:^(id x) {
NSLog(@"2:%@", x);
}];
[connection.signal subscribeNext:^(id x) {
NSLog(@"3:%@", x);
}];
//进行连接
[connection connect];
}
RACCommand
RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程
- (void) rac_command {
//创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
NSLog(@"%@", input);
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@"额 我是谁"];
//¥¥¥处使用
[subscriber sendCompleted];
return nil;
}];
}];
/*
//方式一:先获取执行命令返回的信号再订阅
RACSignal *singnal = [command execute:@111];
[singnal subscribeNext:^(id _Nullable x) {
NSLog(@"这是什么:%@",x);
}];
*/
/*
//方式二:要先订阅再执行命令
[command.executionSignals subscribeNext:^(id _Nullable x) {
[x subscribeNext:^(id _Nullable x) {
NSLog(@"这是啥:%@",x);
}];
}];
[command execute:@222];
*/
/*
//方式三:要先订阅再执行命令,订阅方式有差异
[command.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"这是啥:%@",x);
}];
[command execute:@333];
*/
//¥¥¥
[command.executing subscribeNext:^(NSNumber * _Nullable x) {
if ([x boolValue] == YES) {
NSLog(@"正在执行:%@", x);
}
else {
NSLog(@"执行完成或者没有执行");
}
}];
[command execute:@444];
}
生活如此美好,今天就点到为止。。。