ReactiveCocoa RAC 响应式函数编程(FRP)
来源:互联网 发布:ipad pro实用软件 编辑:程序博客网 时间:2024/04/30 10:25
RACSignal
/** * 手动创建信号 * * 其中的:RACDisposable 当调用 [subscriber sendCompleted]或者[subscriber sendError:nil] 自动调用 可以返回nil * */ RACSignal *signal=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"signal send next"]; [subscriber sendCompleted]; //[subscriber sendError:nil]; return [RACDisposable disposableWithBlock:^{ NSLog(@"signal 发送完成销毁"); }]; }]; /** * 给信号添加订阅者 * * @param x 调用订阅者的 [subscriber sendNext:@"signal send next"] subscribeNext 中传的就是sendNext传递的value * * * @return RACDisposable 可用于手动调用销毁信号 */ RACDisposable *disposal= [signal subscribeNext:^(id x) { NSLog(@"signal 给订阅者发送信号:%@",x); } error:^(NSError *error) { NSLog(@"signal 发生错误"); }]; //[disposal dispose]; [[self rac_signalForSelector:@selector(test)] subscribeNext:^(id x) { NSLog(@"test 调用");//执行了test 方法后调用next }];
事件,KVO,通知等
// @weakify(self) 避免循环引用 @weakify(self); /** * 监听文本的输入 * * @param x TextFiled 的text 类型为id 可以直接修改NSString * * @return */ [[self.mTextFiled1 rac_textSignal] subscribeNext:^(NSString *value) { NSLog(@"文本1:%@",value); }]; /** * 监听按钮点击 * * @param x value 为按钮本身 * * @return */ [[self.mButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *button) { button.backgroundColor=[UIColor yellowColor]; NSLog(@"点击了按钮"); }]; /** * kvo * * @param self.person target * @param name keypath * skip:1 忽略第一次name的信号,name 第一次为nil 也会发出信号 * @return */ [[RACObserve(self.person, name) skip:1]subscribeNext:^(NSString *value) { @strongify(self); [self.mButton setTitle:value forState:UIControlStateNormal]; }]; /** * RAC(target,property)=信号 * RAC 宏 target.property=信号的subscribeNext 传递的值 */ RAC(self.person,name)=self.mTextFiled1.rac_textSignal; /** * 通知 * * @param x 通知 * * @return * takeUntil 取消订阅的信号 self.rac_willDeallocSignal 当前self即将销毁的时候会取消订阅 */ [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) { NSLog(@"通知%@",x); }]; /* * 代理:创建 =[[RACDelegateProxy alloc] initWithProtocol:@protocol(协议名称)] * 成为代理:vc.delegate=(id<ToViewControllerDelegate>)self.proxy; 强制类型转换即可 */ self.proxy=[[RACDelegateProxy alloc] initWithProtocol:@protocol(ToViewControllerDelegate)]; [[self.proxy signalForSelector:@selector(toViewControllerAction:p2:)] subscribeNext:^(RACTuple *value) { /** * 元组解包 * p1=value.first p2.value.second */ RACTupleUnpack(NSString *p1,NSString *p2)=value; NSLog(@"ToViewControllerDelegate 的 toViewControllerAction 方法执行了 参数1%@ 参数2:%@",p1,value.second); }];
RACSuject
/** * RACSubject 本身就是信号,同时自己发送信号 调用sendNext 其他订阅者可以接收到信号 * RACSubject 创建本身不需要block * RACSubject 常用于代理 */ RACSubject *racSuject=[RACSubject subject]; [racSuject subscribeNext:^(id x) { NSLog(@"订阅1"); }]; [racSuject subscribeNext:^(id x) { NSLog(@"订阅2"); }]; [racSuject sendNext:racSuject]; ToViewController *vc=[ToViewController new]; //创建代理 vc.signalDelegate=[RACSubject subject]; //订阅 [vc.signalDelegate subscribeNext:^(RACTuple *value) { /** * 第一个参数设置为int类型 假设多个代理方法的时候,就可以用这种方法去处理代理的不同方法 可以将这个参数设置为常量 */ switch ([value.first integerValue]) { case 1: NSLog(@"执行代理方法 参数1:%@ 参数2:%@",value.second,value.third); break; default: break; } }]; [self.navigationController pushViewController:vc animated:YES];
RACReplaySubject
/** * RACReplaySubject 可以先发送信号,在订阅 RACSubject 不可以 * RACReplaySubject 先将value 保存起来 有新的订阅者就会将之前的所有的value重新发送一遍 * RACSubject 保存的订阅者,有新的者,遍历订阅者一个个发送 */ RACReplaySubject *replaySubject=[RACReplaySubject subject]; [replaySubject sendNext:@"1"]; [replaySubject sendNext:@"2"]; [replaySubject subscribeNext:^(id x) { NSLog(@"订阅者1 接收的value:%@",x); }]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [replaySubject subscribeNext:^(id x) { NSLog(@"订阅者2 接收的value:%@",x); }]; });
RACSequence
/** * * RACSequence :集合 * 1.集合转换为集合信号RACSequence rac_sequence * 2.订阅信号中的信号 rac_sequence.signal */ NSArray *array=@[@1,@2,@3,@4]; [array.rac_sequence.signal subscribeNext:^(id x) { NSLog(@"遍历数组%@",x); }]; NSDictionary *dict=@{@"key1":@1,@"key2":@2}; [dict.rac_sequence.signal subscribeNext:^(RACTuple *value) { NSLog(@"遍历字典 key:%@ value:%@",value.first,value.second); }];
RACCommand
/** * RACCommand 命令 多用于网络请求,因为它可以监听sinal的请求状态 * */ RACCommand *racCommand=[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) { NSLog(@"start command"); //return [RACSignal empty]; 必须返回信号,不可以返回nil return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{ [subscriber sendNext:@"下载的数据"]; [subscriber sendCompleted]; }); return nil; }]; }]; /** * 强引用,不然会被销毁 */ _racCommand=racCommand; /** * executionSignals 获取命令中执行返回的信号 */ [_racCommand.executionSignals subscribeNext:^(id x) { [x subscribeNext:^(id x) { NSLog(@"订阅1 请求数据 %@",x); }]; }]; /* _racCommand.executionSignals.switchToLatest 获取最后一个信号 常用获取命令中的信号 */ [_racCommand.executionSignals.switchToLatest subscribeNext:^(id x) { NSLog(@"订阅2 请求的数据%@",x); }]; [[_racCommand.executing skip:1] subscribeNext:^(id x) { if([x boolValue]){ NSLog(@"命令正在执行过程中"); }else{ NSLog(@"命令完成"); } }]; //执行命令 [self.racCommand execute:@1];
信号绑定
@weakify(self); [[self.mTextFiled1.rac_textSignal bind:^RACStreamBindBlock{ /* * 当原信号发出的时候,就会执行以下block * block 处理原来的信号 * 返回新的信号 RACReturnSignal 需要导入<ReactiveCocoa/RACReturnSignal.h> * (id value,BOOL *stop) value 为原信号的value stop=yes 就会结束绑定 * */ return ^RACStream *(id value,BOOL *stop){ *stop=self.stop; NSLog(@"处理绑定的信号"); return [RACReturnSignal return:[NSString stringWithFormat:@"bind%@",value]]; }; }] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"取消了绑定"); self.stop=YES;//2 秒后取消绑定,但是还是会执行一次,因为执行一次后,才会重新赋值为Yes,取消绑定 });
映射
/** 原理绑定 如果信号发出的值不是信号,映射一般使用Map 发出的值是信号 flattenMap */ @weakify(self); [[self.mTextFiled1.rac_textSignal flattenMap:^RACStream *(id value) { NSLog(@"处理绑定的信号"); return [RACReturnSignal return:[NSString stringWithFormat:@"bind%@",value]]; }] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }]; /* * 同样还是绑定 常用于修改原信号的返回值,返回自己想要的值 */ [[self.mTestField2.rac_textSignal map:^id(id value) { return [NSString stringWithFormat:@"bind2%@",value]; }] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }];
过滤等
@weakify(self); /* * filter返回Yes 的信号才会往下传递 */ [[self.mTextFiled1.rac_textSignal filter:^BOOL(NSString *value) { return [value isEqualToString:@"filter"]; }] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }]; /* *忽略ignore的value 例如以下123 不会发出信号 */ [[self.mTestField2.rac_textSignal ignore:@"123"] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }]; //distinctUntilChanged 当上次一次信号的值和新的一次的值不一样的时候才会发出信号,常用于UI的刷新 [[self.mTestField2.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }]; /* * take :次数 发出限定次数后不在订阅 以下的方法实际只会看到textFiled输入一次后就不会改变了,默认执行1次,textfiled获取焦点执行一次,输入执行一次 */ [[self.mTextFiled1.rac_textSignal take:3] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }]; /** * takeLast 只取最后n次,但是前提是sendCompleted 就是必须知道这个信号发出几次后才能确定最后n次信号,是那几个信号 * 还有skip 跳过前 n次信号 switchToLatest 取最后一次信号发送,同样需要调用 sendCompleted */ RACSubject *subject=[RACSubject subject]; [[subject takeLast:1] subscribeNext:^(id x) { @strongify(self); [self.mButton setTitle:x forState:UIControlStateNormal]; }]; /** * 发送信号必须在订阅之后 */ [subject sendNext:@"1"]; [subject sendNext:@"2"]; [subject sendNext:@"3"]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [subject sendCompleted]; });
连接
/* * *concat 信号源1 连接 信号源2 信号1调用completed才会执行发送信号2 *可以使用then连接,原理是concat,concat实际是过滤信号2的发出的信号,当信号1结束只会才会执行信号源2发送的信号 * merge 合并信号(或|合并)只要有个信号源发出信号,就会执行订阅者的block * zipWith: 合并信号(且|合并) 两个信号同时发出才会执行,value是一个元组 */ RACSignal *signal1=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"1"]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{ [subscriber sendCompleted]; }); return nil; }]; RACSignal *singal2=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"2"]; return nil; }]; RACSignal *connect=[signal1 concat:singal2]; [connect subscribeNext:^(id value) { NSLog(@"接受到信号%@",value); }];
合并
/* * comLast 合并最新的信号 reduce 聚合 */ RACSignal *signal=[RACSignal combineLatest: @[ [ self.mTextFiled1.rac_textSignal filter:^BOOL(NSString *value) { return value.length>2; }], [self.mTestField2.rac_textSignal filter:^BOOL(NSString *value) { return value.length>2; }] ] reduce:^id(NSString *v1,NSString *v2){//默认空参数,可以手动添加 return [NSString stringWithFormat:@"%@-%@",v1,v2]; }]; RAC(self.mButton,backgroundColor)=[signal map:^id(NSString *value) { NSLog(@"%@",value); return [value isEqualToString:@"123-123456"]?[UIColor blackColor]:[UIColor redColor]; }];
Time相关
/* * timeout: 2 2后自动调用 error */ [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { return nil; }] timeout:2 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) { NSLog(@"1.timeout next"); } error:^(NSError *error) { //两秒后自定调用error NSLog(@"1.timeout error"); }]; /* delay:2 2秒执行block */ [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"2"]; return nil; }] delay:2] subscribeNext:^(id x) { NSLog(@"2s: %@",x); }]; static int i=0; /* retry 只要sendError 就会重新执行一次block 直到成功 */ [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { if(i>5){ [subscriber sendNext:@"2"]; [subscriber sendCompleted]; NSLog(@"next i:%d",i); }else{ [subscriber sendError:nil]; NSLog(@"error i:%d",i); i++; } return nil; }] retry] subscribeNext:^(id x) { NSLog(@"---data:%@",x); }];
0 0
- ReactiveCocoa RAC 响应式函数编程(FRP)
- 函数响应式编程(FRP)框架--ReactiveCocoa
- 函数响应式编程(FRP)框架--ReactiveCocoa
- 函数响应式编程(FRP)与 ReactiveCocoa
- ReactiveCocoa 框架 (一)-- 函数响应式编程(FRP)框架
- 函数响应式编程(FRP)思想
- IOS响应式编程框架ReactiveCocoa(RAC)
- iOS响应式编程框架ReactiveCocoa(RAC)
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- TUNA下载Android源码
- ext js 学习系列 二 MVC 框架的搭建 .
- oc学习笔记-复制对象
- 右左法则----复杂指针解析
- WindowsForm应用程序调用WebService
- ReactiveCocoa RAC 响应式函数编程(FRP)
- 宝岛探险
- [leetcode 298] Binary Tree Longest Consecutive Sequence---求二叉树连续序列的长度
- ECNU_OJ_1006
- 开发中常用的一些命令
- 自定义dedecms栏目的排列顺序
- 字符串操作题
- VM虚拟机 NAT网络设置
- 抗合谋数字指纹嵌入及其追踪技术