ReactiveCocoa RAC 响应式函数编程(FRP)

前端之家收集整理的这篇文章主要介绍了ReactiveCocoa RAC 响应式函数编程(FRP)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

RACSignal

  1. /** * 手动创建信号 * * 其中的:RACDisposable 当调用 [subscriber sendCompleted]或者[subscriber sendError:nil] 自动调用 可以返回nil * */
  2. RACSignal *signal=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  3.  
  4.  
  5. [subscriber sendNext:@"signal send next"];
  6. [subscriber sendCompleted];
  7.  
  8. //[subscriber sendError:nil];
  9.  
  10.  
  11. return [RACDisposable disposableWithBlock:^{
  12. NSLog(@"signal 发送完成销毁");
  13. }];
  14. }];
  15.  
  16.  
  17. /** * 给信号添加订阅者 * * @param x 调用订阅者的 [subscriber sendNext:@"signal send next"] subscribeNext 中传的就是sendNext传递的value * * * @return RACDisposable 可用于手动调用销毁信号 */
  18. RACDisposable *disposal= [signal subscribeNext:^(id x) {
  19. NSLog(@"signal 给订阅者发送信号:%@",x);
  20. } error:^(NSError *error) {
  21. NSLog(@"signal 发生错误");
  22. }];
  23.  
  24. //[disposal dispose];
  25. [[self rac_signalForSelector:@selector(test)] subscribeNext:^(id x) {
  26. NSLog(@"test 调用");//执行了test 方法调用next
  27. }];

事件,KVO,通知

  1. // @weakify(self) 避免循环引用
  2. @weakify(self);
  3. /** * 监听文本的输入 * * @param x TextFiled 的text 类型为id 可以直接修改NSString * * @return */
  4. [[self.mTextFiled1 rac_textSignal] subscribeNext:^(NSString *value) {
  5. NSLog(@"文本1:%@",value);
  6. }];
  7.  
  8.  
  9.  
  10. /** * 监听按钮点击 * * @param x value 为按钮本身 * * @return */
  11. [[self.mButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *button) {
  12. button.backgroundColor=[UIColor yellowColor];
  13. NSLog(@"点击了按钮");
  14. }];
  15.  
  16. /** * kvo * * @param self.person target * @param name keypath * skip:1 忽略第一次name的信号,name 第一次为nil 也会发出信号 * @return */
  17. [[RACObserve(self.person,name) skip:1]subscribeNext:^(NSString *value) {
  18. @strongify(self);
  19. [self.mButton setTitle:value forState:UIControlStateNormal];
  20. }];
  21.  
  22. /** * RAC(target,property)=信号 * RAC 宏 target.property=信号的subscribeNext 传递的值 */
  23. RAC(self.person,name)=self.mTextFiled1.rac_textSignal;
  24. /** * 通知 * * @param x 通知 * * @return * takeUntil 取消订阅的信号 self.rac_willDeallocSignal 当前self即将销毁的时候会取消订阅 */
  25. [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {
  26. NSLog(@"通知%@",x);
  27. }];
  28.  
  29. /* * 代理:创建 =[[RACDelegateProxy alloc] initWithProtocol:@protocol(协议名称)] * 成为代理:vc.delegate=(id<ToViewControllerDelegate>)self.proxy; 强制类型转换即可 */
  30. self.proxy=[[RACDelegateProxy alloc] initWithProtocol:@protocol(ToViewControllerDelegate)];
  31. [[self.proxy signalForSelector:@selector(toViewControllerAction:p2:)] subscribeNext:^(RACTuple *value) {
  32.  
  33. /** * 元组解包 * p1=value.first p2.value.second */
  34. RACTupleUnpack(NSString *p1,NSString *p2)=value;
  35.  
  36. NSLog(@"ToViewControllerDelegate 的 toViewControllerAction 方法执行了 参数1%@ 参数2:%@",p1,value.second);
  37. }];

RACSuject

  1. /** * RACSubject 本身就是信号,同时自己发送信号 调用sendNext 其他订阅者可以接收到信号 * RACSubject 创建本身不需要block * RACSubject 常用于代理 */
  2. RACSubject *racSuject=[RACSubject subject];
  3.  
  4.  
  5.  
  6. [racSuject subscribeNext:^(id x) {
  7. NSLog(@"订阅1");
  8. }];
  9. [racSuject subscribeNext:^(id x) {
  10. NSLog(@"订阅2");
  11. }];
  12.  
  13. [racSuject sendNext:racSuject];
  14.  
  15.  
  16. ToViewController *vc=[ToViewController new];
  17. //创建代理
  18. vc.signalDelegate=[RACSubject subject];
  19. //订阅
  20. [vc.signalDelegate subscribeNext:^(RACTuple *value) {
  21. /** * 第一个参数设置为int类型 假设多个代理方法的时候,就可以用这种方法去处理代理的不同方法 可以将这个参数设置为常量 */
  22. switch ([value.first integerValue]) {
  23. case 1:
  24. NSLog(@"执行代理方法 参数1:%@ 参数2:%@",value.second,value.third);
  25. break;
  26. default:
  27. break;
  28. }
  29. }];
  30. [self.navigationController pushViewController:vc animated:YES];

RACReplaySubject

  1. /** * RACReplaySubject 可以先发送信号,在订阅 RACSubject 不可以 * RACReplaySubject 先将value 保存起来 有新的订阅者就会将之前的所有的value重新发送一遍 * RACSubject 保存的订阅者,有新的者,遍历订阅者一个个发送 */
  2. RACReplaySubject *replaySubject=[RACReplaySubject subject];
  3. [replaySubject sendNext:@"1"];
  4. [replaySubject sendNext:@"2"];
  5. [replaySubject subscribeNext:^(id x) {
  6. NSLog(@"订阅者1 接收的value:%@",x);
  7. }];
  8. dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2 * NSEC_PER_SEC)),dispatch_get_main_queue(),^{
  9. [replaySubject subscribeNext:^(id x) {
  10. NSLog(@"订阅者2 接收的value:%@",x);
  11. }];
  12. });

RACSequence

  1. /** * * RACSequence :集合 * 1.集合转换为集合信号RACSequence rac_sequence * 2.订阅信号中的信号 rac_sequence.signal */
  2. NSArray *array=@[@1,@2,@3,@4];
  3. [array.rac_sequence.signal subscribeNext:^(id x) {
  4. NSLog(@"遍历数组%@",x);
  5. }];
  6. NSDictionary *dict=@{@"key1":@1,@"key2":@2};
  7. [dict.rac_sequence.signal subscribeNext:^(RACTuple *value) {
  8. NSLog(@"遍历字典 key:%@ value:%@",value.first,value.second);
  9. }];

RACCommand

  1. /** * RACCommand 命令 多用于网络请求,因为它可以监听sinal的请求状态 * */
  2. RACCommand *racCommand=[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
  3. NSLog(@"start command");
  4. //return [RACSignal empty]; 必须返回信号,不可以返回nil
  5. return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  6. dispatch_after(dispatch_time(DISPATCH_TIME_NOW,dispatch_get_global_queue(0,0),^{
  7. [subscriber sendNext:@"下载的数据"];
  8. [subscriber sendCompleted];
  9. });
  10. return nil;
  11. }];
  12. }];
  13. /** * 强引用,不然会被销毁 */
  14. _racCommand=racCommand;
  15.  
  16. /** * executionSignals 获取命令中执行返回的信号 */
  17. [_racCommand.executionSignals subscribeNext:^(id x) {
  18. [x subscribeNext:^(id x) {
  19. NSLog(@"订阅1 请求数据 %@",x);
  20. }];
  21. }];
  22. /* _racCommand.executionSignals.switchToLatest 获取最后一个信号 常用获取命令中的信号 */
  23. [_racCommand.executionSignals.switchToLatest subscribeNext:^(id x) {
  24. NSLog(@"订阅2 请求的数据%@",x);
  25. }];
  26. [[_racCommand.executing skip:1] subscribeNext:^(id x) {
  27. if([x boolValue]){
  28. NSLog(@"命令正在执行过程中");
  29. }else{
  30. NSLog(@"命令完成");
  31. }
  32. }];
  33. //执行命令
  34. [self.racCommand execute:@1];

信号绑定

  1. @weakify(self);
  2. [[self.mTextFiled1.rac_textSignal bind:^RACStreamBindBlock{
  3.  
  4. /* * 当原信号发出的时候,就会执行以下block * block 处理原来的信号 * 返回新的信号 RACReturnSignal 需要导入<ReactiveCocoa/RACReturnSignal.h> * (id value,BOOL *stop) value 为原信号的value stop=yes 就会结束绑定 * */
  5. return ^RACStream *(id value,BOOL *stop){
  6. *stop=self.stop;
  7. NSLog(@"处理绑定的信号");
  8. return [RACReturnSignal return:[NSString stringWithFormat:@"bind%@",value]];
  9. };
  10. }] subscribeNext:^(id x) {
  11. @strongify(self);
  12. [self.mButton setTitle:x forState:UIControlStateNormal];
  13. }];
  14.  
  15.  
  16. dispatch_after(dispatch_time(DISPATCH_TIME_NOW,^{
  17. NSLog(@"取消了绑定");
  18. self.stop=YES;//2 秒后取消绑定,但是还是会执行一次,因为执行一次后,才会重新赋值为Yes,取消绑定
  19. });

映射

  1. /** 原理绑定 如果信号发出的值不是信号,映射一般使用Map 发出的值是信号 flattenMap */
  2. @weakify(self);
  3. [[self.mTextFiled1.rac_textSignal flattenMap:^RACStream *(id value) {
  4. NSLog(@"处理绑定的信号");
  5. return [RACReturnSignal return:[NSString stringWithFormat:@"bind%@",value]];
  6. }] subscribeNext:^(id x) {
  7. @strongify(self);
  8. [self.mButton setTitle:x forState:UIControlStateNormal];
  9. }];
  10. /* * 同样还是绑定 常用于修改原信号的返回值,返回自己想要的值 */
  11. [[self.mTestField2.rac_textSignal map:^id(id value) {
  12. return [NSString stringWithFormat:@"bind2%@",value];
  13. }] subscribeNext:^(id x) {
  14. @strongify(self);
  15. [self.mButton setTitle:x forState:UIControlStateNormal];
  16. }];

过滤等

  1. @weakify(self);
  2. /* * filter返回Yes 的信号才会往下传递 */
  3. [[self.mTextFiled1.rac_textSignal filter:^BOOL(NSString *value) {
  4. return [value isEqualToString:@"filter"];
  5. }] subscribeNext:^(id x) {
  6. @strongify(self);
  7. [self.mButton setTitle:x forState:UIControlStateNormal];
  8. }];
  9. /* *忽略ignore的value 例如以下123 不会发出信号 */
  10. [[self.mTestField2.rac_textSignal ignore:@"123"] subscribeNext:^(id x) {
  11. @strongify(self);
  12. [self.mButton setTitle:x forState:UIControlStateNormal];
  13.  
  14. }];
  15.  
  16. //distinctUntilChanged 当上次一次信号的值和新的一次的值不一样的时候才会发出信号,常用于UI的刷新
  17. [[self.mTestField2.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {
  18. @strongify(self);
  19. [self.mButton setTitle:x forState:UIControlStateNormal];
  20. }];
  21.  
  22. /* * take :次数 发出限定次数后不在订阅 以下的方法实际只会看到textFiled输入一次后就不会改变了,默认执行1次,textfiled获取焦点执行一次,输入执行一次 */
  23.  
  24. [[self.mTextFiled1.rac_textSignal take:3] subscribeNext:^(id x) {
  25. @strongify(self);
  26. [self.mButton setTitle:x forState:UIControlStateNormal];
  27. }];
  28. /** * takeLast 只取最后n次,但是前提是sendCompleted 就是必须知道这个信号发出几次后才能确定最后n次信号,是那几个信号 * 还有skip 跳过前 n次信号 switchToLatest 取最后一次信号发送,同样需要调用 sendCompleted */
  29. RACSubject *subject=[RACSubject subject];
  30. [[subject takeLast:1] subscribeNext:^(id x) {
  31. @strongify(self);
  32. [self.mButton setTitle:x forState:UIControlStateNormal];
  33. }];
  34. /** * 发送信号必须在订阅之后 */
  35. [subject sendNext:@"1"];
  36. [subject sendNext:@"2"];
  37. [subject sendNext:@"3"];
  38.  
  39. dispatch_after(dispatch_time(DISPATCH_TIME_NOW,^{
  40. [subject sendCompleted];
  41. });

连接

  1. /* * *concat 信号源1 连接 信号源2 信号1调用completed才会执行发送信号2 *可以使用then连接,原理是concat,concat实际是过滤信号2的发出的信号,当信号1结束只会才会执行信号源2发送的信号 * merge 合并信号(或|合并)只要有个信号源发出信号,就会执行订阅者的block * zipWith: 合并信号(且|合并) 两个信号同时发出才会执行,value是一个元组 */
  2.  
  3. RACSignal *signal1=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  4. [subscriber sendNext:@"1"];
  5. dispatch_after(dispatch_time(DISPATCH_TIME_NOW,^{
  6. [subscriber sendCompleted];
  7. });
  8. return nil;
  9. }];
  10.  
  11. RACSignal *singal2=[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  12. [subscriber sendNext:@"2"];
  13. return nil;
  14. }];
  15.  
  16. RACSignal *connect=[signal1 concat:singal2];
  17.  
  18. [connect subscribeNext:^(id value) {
  19. NSLog(@"接受到信号%@",value);
  20. }];

合并

  1. /* * comLast 合并最新的信号 reduce 聚合 */
  2. RACSignal *signal=[RACSignal combineLatest:
  3. @[
  4. [ self.mTextFiled1.rac_textSignal filter:^BOOL(NSString *value) {
  5. return value.length>2;
  6. }],[self.mTestField2.rac_textSignal filter:^BOOL(NSString *value) {
  7. return value.length>2;
  8. }]
  9. ]
  10. reduce:^id(NSString *v1,NSString *v2){//默认空参数,可以手动添加
  11. return [NSString stringWithFormat:@"%@-%@",v1,v2];
  12. }];
  13. RAC(self.mButton,backgroundColor)=[signal map:^id(NSString *value) {
  14. NSLog(@"%@",value);
  15. return [value isEqualToString:@"123-123456"]?[UIColor blackColor]:[UIColor redColor];
  16. }];

Time相关

  1. /* * timeout: 2 2后自动调用 error */
  2. [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  3. return nil;
  4. }] timeout:2 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
  5. NSLog(@"1.timeout next");
  6. } error:^(NSError *error) {
  7. //两秒后自定调用error
  8. NSLog(@"1.timeout error");
  9. }];
  10. /* delay:2 2秒执行block */
  11. [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  12. [subscriber sendNext:@"2"];
  13. return nil;
  14. }] delay:2] subscribeNext:^(id x) {
  15. NSLog(@"2s: %@",x);
  16. }];
  17. static int i=0;
  18.  
  19. /* retry 只要sendError 就会重新执行一次block 直到成功 */
  20. [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  21. if(i>5){
  22. [subscriber sendNext:@"2"];
  23. [subscriber sendCompleted];
  24. NSLog(@"next i:%d",i);
  25. }else{
  26. [subscriber sendError:nil];
  27. NSLog(@"error i:%d",i);
  28. i++;
  29. }
  30. return nil;
  31. }] retry] subscribeNext:^(id x) {
  32. NSLog(@"---data:%@",x);
  33. }];

猜你在找的React相关文章