ReactiveCocoa(FRP)-进阶篇(下)

简介: ReactiveCocoa(FRP)-进阶篇(下)
  • 1.5.3.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(@"%@",x);
}];

merge底层实现:


- 1.合并信号被订阅的时候,就会遍历所有信号,并且发出这些信号。

- 2.每发出一个信号,这个信号就会被订阅

- 3.也就是合并信号一被订阅,就会订阅里面所有的信号。

- 4.只要有一个信号被发出就会被监听。


  • 1.5.4.zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件::----夫妻关系


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:^(id x) {
     NSLog(@"%@",x);
}];


image.png


底层实现:
  - 1.定义压缩信号,内部就会自动订阅signalA,signalB
  - 2.每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出。
  • 1.5.5.combineLatest(重要)combineLatest:将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号


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;
}];
// 把两个信号组合成一个信号,跟zip一样,没什么区别
RACSignal *combineSignal = [signalA combineLatestWith:signalB];
   [combineSignal subscribeNext:^(id x) {
    NSLog(@"%@",x);
}];
  • combineLatest底层实现


  • 1.当组合信号被订阅,内部会自动订阅signalA,signalB,必须两个信号都发出内容,才会被触发。
  • 2.并且把两个信号组合成元组发出。


image.png

1.6 ReactiveCocoa操作方法之过滤


  • 1.6.1.filter过滤信号,使用它可以获取满足条件的信号


image.png

#pragma mark filter
    -(void)filter
    {
         // 过滤:
        // 每次信号发出,会先执行过滤条件判断.
       [[_textField.rac_textSignal filter:^BOOL(NSString *value) {
           return value.length > 3;
       }] subscribeNext:^(id x) {
          NSLog(@"%@",x);
       }];
    }


  • 1.6.2.ignore:忽略完某些值的信号


image.png


// ignore: 忽略一些值
  // ignoreValues: 忽略所有的值
  //1.创建信号
  RACSubject *subject = [RACSubject subject];
  //2.忽略一些
  RACSignal *ignoreSignal = [subject ignore:@12];//ignore相当于判断一下
  //3.订阅信号
  [ignoreSignal subscribeNext:^(id x) {
  //5.打印果略后的数据
     NSLog(@"%@",x);
  }];
  //4.发送数据
  [subject sendNext:@"1"];


  • 1.6.3.take:从开始一共取N次的信号

image.png


// 1、创建信号
 RACSubject *signal = [RACSubject subject];
 // 2、处理信号,订阅信号
 [[signal take:2] subscribeNext:^(id x) {
        NSLog(@"%@",x);
 }];
 // 3.发送信号
 [signal sendNext:@1];
 [signal sendNext:@2];
 [signal sendNext:@3];


  • 1.6.4.takeLast:取最后N次的信号,前提条件,订阅者必须调用完成,因为只有完成,就知道总共有多少信号


image.png

// 1、创建信号
RACSubject *signal = [RACSubject subject];
// 2、处理信号,订阅信号
[[signal takeLast:2] subscribeNext:^(id x) {
      NSLog(@"%@",x);
}];
// 3.发送信号
[signal sendNext:@1];
[signal sendNext:@2];
[signal sendNext:@3];
// 必须设置发送完成
[signal sendCompleted];


  • 1.6.5.takeUntil:(RACSignal *):获取信号直到执行完这个信号,只要传入信号发送完成后或者发送任意数据,就不能再接受源信号的内容
  • 监听文本框的改变,知道当前对象被销毁
[_textField.rac_textSignal takeUntil:self.rac_willDeallocSignal];


信号处理


image.png


// takeUntil: 只要传入信号发送完成后或者发送任意数据,就不能再接受源信号的内容
  // 1、创建信号
   RACSubject *signal = [RACSubject subject];
   RACSubject *subject = [RACSubject subject];
  // 2、处理信号,订阅信号
  [[signal takeUntil:subject] subscribeNext:^(id x) {
         NSLog(@"%@",x);
   }];
   // 3.发送信号
   [signal sendNext:@1];
   [signal sendNext:@2];
  // [subject sendCompleted];
     [subject sendNext:@"hello"];
   [signal sendNext:@3];
  • 1.6.6.distinctUntilChanged:当上一次的值和当前的值有明显的变化就会发出信号,否则会被忽略掉


// 过滤,当上一次和当前的值不一样,就会发出内容。
 // 在开发中,刷新UI经常使用,只有两次数据不一样才需要刷新
 [[_textField.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {
       NSLog(@"%@",x);
 }];


image.png



// 创建信号

RACSubject *subject = [RACSubject subject];

// 订阅信号

[[subject distinctUntilChanged] subscribeNext:^(id x) {



NSLog(@"%@",x);
   }];
  [subject sendNext:@"1"];
  [subject sendNext:@"2"];
  [subject sendNext:@"2"];
  [subject sendNext:@"1"];


  • 1.6.7.skip:(NSUInteger):跳过几个信号,不接受


image.png


  • 1.6.8.switchToLatest:用于signalOfSignals(信号的信号),有时候信号也会发出信号,会在signalOfSignals中,获取signalOfSignals发送的最新信号。


RACSubject *signalOfSignals = [RACSubject subject];
 RACSubject *signal = [RACSubject subject];
 [signalOfSignals sendNext:signal];
 [signal sendNext:@1];
 // 获取信号中信号最近发出信号,订阅最近发出的信号。
 // 注意switchToLatest:只能用于信号中的信号
     [signalOfSignals.switchToLatest subscribeNext:^(id x) {
       NSLog(@"%@",x);
    }];
  • 1.7 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);
}];
  • 1.8 ReactiveCocoa操作方法之线程


  • deliverOn: 内容传递切换到制定线程中,副作用在原来线程中,把在创建信号时block中的代码称之为副作用。
  • subscribeOn: 内容传递和副作用都会切换到制定线程中。


  • 1.9 ReactiveCocoa操作方法之时间


  • 1.9.1.timeout:超时,可以让一个信号在一定的时间后,自动报错


RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    return nil;
}] timeout:1 onScheduler:[RACScheduler currentScheduler]];
[signal subscribeNext:^(id x) {
       NSLog(@"%@",x);
 } error:^(NSError *error) {
      // 1秒后会自动调用
     NSLog(@"%@",error);
}];


image.png

  • 1.9.2.interval 定时:每隔一段时间发出信号


[[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
      NSLog(@"%@",x);
 }];


image.png

1.9.3.delay 延迟发送next


image.png

[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     [subscriber sendNext:@1];
     return nil;
 }] delay:3] subscribeNext:^(id x) {
     NSLog(@"%@",x);
 }];
  • 1.10. ReactiveCocoa操作方法之重复


  • 1.10.1.retry重试 :只要失败,就会重新执行创建信号中的block,直到成功.


__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(@"%@",x);
   } error:^(NSError *error) {
}];


image.png


  • 1.10.2.replay重放:当一个信号被多次订阅,反复播放内容


image.png



RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id subscriber) {


[subscriber sendNext:@1];
         [subscriber sendNext:@2];
         return nil;
     }] replay];
     [signal subscribeNext:^(id x) {
          NSLog(@"第一个订阅者%@",x);
     }];
    [signal subscribeNext:^(id x) {
         NSLog(@"第二个订阅者%@",x);
     }];


  • 1.10.3.throttle节流:当某个信号发送比较频繁时,可以使用节流,在某一段时间不发送信号内容,过了一段时间获取信号的最新内容发出


image.png

RACSubject *signal = [RACSubject subject];
 // 节流,在一定时间(1秒)内,不接收任何信号内容,过了这个时间(1秒)获取最后发送的信号内容发出。
 [[signal throttle:5] subscribeNext:^(id x) {
        NSLog(@"%@",x);
 }];
 [signal sendNext:@"我是在5s之后打印的"];
目录
相关文章
|
2月前
|
PHP Windows
thinkPhP6.0安装教程图解--PHP框架安装
本文是一篇关于ThinkPHP 6.0安装教程的图解,包括环境检查、安装Composer、修改Composer镜像地址、安装ThinkPHP框架以及启动运行ThinkPHP的步骤。文章详细描述了每个步骤的操作方法,并提供了相应的命令和截图,帮助用户理解并顺利完成ThinkPHP 6.0的安装和运行。
thinkPhP6.0安装教程图解--PHP框架安装
|
3月前
|
开发工具 图形学 Android开发
从零开始的unity3d入门教程(一)----环境配置
该文章是《从零开始的Unity3D入门教程》系列的第一篇,详细介绍了Unity3D的环境配置过程,包括注册Unity账户、下载安装Unity Hub和Unity编辑器、配置许可证、创建Unity项目、下载安装Visual Studio 2022以及将Unity与Visual Studio相关联等步骤。
从零开始的unity3d入门教程(一)----环境配置
|
3月前
|
定位技术 C# 图形学
从零开始的unity3d入门教程(二)----基本功能讲解
这是一篇Unity3D入门教程,详细介绍了Unity界面操作、游戏物体创建修改、场景搭建、玩家控制、音效添加以及游戏测试和导出的全过程。
从零开始的unity3d入门教程(二)----基本功能讲解
|
机器学习/深度学习 存储 JavaScript
你就是函数响应式编程(FRP)啊?!【附 RxJS 实战】
什么是 FRP? 英文全称是:Functional Reactive Programming,翻译过来就是:函数响应式编程。
|
安全 Java Linux
手把手教你搭个Frida + Sekiro Rpc框架
手把手教你搭个Frida + Sekiro Rpc框架
手把手教你搭个Frida + Sekiro Rpc框架
|
存储 前端开发 JavaScript
werkzeug源码阅读-完结篇
Werkzeug是一个全面的WSGI Web应用程序库。它最初是WSGI实用程序各种工具的简单集合,现已成为最高级的WSGI实用程序库之一,是Flask背后的项目。
503 0
werkzeug源码阅读-完结篇
|
应用服务中间件 nginx
Phalcon如何创建多模块并能进行访问 《Phalcon入坑指南系列 四》(1)
Phalcon如何创建多模块并能进行访问 《Phalcon入坑指南系列 四》
197 0
Phalcon如何创建多模块并能进行访问 《Phalcon入坑指南系列 四》(1)
|
容器
Phalcon如何创建多模块并能进行访问 《Phalcon入坑指南系列 四》(2)
Phalcon如何创建多模块并能进行访问 《Phalcon入坑指南系列 四》
173 0
Phalcon如何创建多模块并能进行访问 《Phalcon入坑指南系列 四》(2)
|
Web App开发 监控 Shell
实现原理讲解,我强烈推荐你看看这-22-款超好用的命令行工具
实现原理讲解,我强烈推荐你看看这-22-款超好用的命令行工具
实现原理讲解,我强烈推荐你看看这-22-款超好用的命令行工具
下一篇
无影云桌面