RAC基础笔记

RACSignal:

信号类,当数据改变的时候,内部会发出信号,本身不能发送信号,而是交给一个订阅者(RACSubscriber)去发送,创建的时候block内部会带一个订阅者。

RACSubscriber:

订阅者,本身是个协议,用于发送信号,

RACDisposable:

清洁工,用于取消订阅,或者清理资源,

// 创建信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        //发送信号
        [subscriber sendNext:@"发送消息"];
        //发送信号完成
        [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{

            NSLog(@"信号被销毁");
        }];
    }];

    // 只有订阅信号才能接收到数据
    [signal subscribeNext:^(id x) {
         NSLog(@"接收到数据:%@",x);
    }];

RACCommand:

事件的处理类,运用这个类可以监听到事件执行的整个过程

self.command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
       //默认要创建一个信号,如果不做任何操作可以创建空信号
       // return  [RACSignal empty];

        //input这个参数是执行的时候传入的,根据这个参数可以看出RACCommand的运行过程
       return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {

           //发送
           [subscriber sendNext:input];
           [subscriber sendCompleted];

           return nil;
       }];
    }];

    //订阅(信号中的信号),switchToLatest:获取信号中的信号,有的时候信号也可以发出信号
    [[self.command.executionSignals switchToLatest] subscribeNext:^(id  _Nullable input) {
        NSLog(@"%@",input);
    }];

    //执行
    [self.command execute:@(1)];

RACSubject和RACReplaySubject:

RACSubject可以提供信号,自己也是信号的提供者,

RACReplaySubject是RACSubject子类,可以重复提供信号,可以先发送,再订阅,也可以多次订阅,但是RACSubjec由于过于灵活,官方也不建议使用。

RACSubject * subject = [RACSubject subject];

    //先订阅
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

    //一定要先订阅再发送
    [subject sendNext:@"1"];

    RACReplaySubject  *replaySubject = [RACReplaySubject subject];
    //可以先发送再订阅
    [replaySubject sendNext:@"1"];
    [replaySubject sendNext:@"2"];

    [replaySubject subscribeNext:^(id  _Nullable x) {
        //只要订阅了就会接受到发送的所有数据,所以订阅的block都会执行两次
        NSLog(@"%@",x);
    }];

    [replaySubject subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

4.基本用法

基本宏

1.RAC(TARGET, [KEYPATH, [NIL_VALUE]]) 绑定对象属性

2.RACObserve(self, name) 监听属性变化的信号

3.

//RACTuplePack:把数据包装成元祖
    RACTuple *tuple = RACTuplePack(@(111),@"222");

    //RACTuplePack:解包,把元祖解包成对应的数据类型
    RACTupleUnpack(NSNumber * number,NSString * string) = tuple;
    NSLog(@"%@--%@",number,string);

    //RACTuple提供了直接访问元素的属性
    NSNumber *tNumber = tuple.first;
    NSString *tString = tuple.second;
    NSLog(@"%@--%@",tNumber,tString);

替换传统消息机制

  • rac_signalForSelector 替换代理
  • rac_signalForControlEvents 替换UIControl Target-Action方法
  • rac_valuesAndChangesForKeyPath 替换KVO
  • rac_addObserverForName 替换通知
  • rac_textSignal 替换文本监听代理

rac_signalForSelector替换代理有局限性,只能用于没有返回值的代理

使用基本方法

1.过滤

  • filter
[[self.userNameTF.rac_textSignal
      filter:^BOOL(NSString * value){
          //用户登录的时候限制用户名的长度
          return value.length > 11;
      }]
     subscribeNext:^(id x){
         //过滤信号,符合条件订阅才会接收到
         NSLog(@"%@", x);
     }];
  • distinctUntilChanged: 
    也有过滤的功能,当信号中上一次的值与当前的值又变化的时候,就会发出信号。
  • take,takeLast,skip
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"1"];
        [subscriber sendNext:@"2"];
        [subscriber sendNext:@"3"];
        [subscriber sendCompleted];
        return nil;
    }];
    [[signal take:2] subscribeNext:^(id  _Nullable x) {
        //订阅信号,“2”代表取前两次的信号,打印1,2
        NSLog(@"%@",x);
    }];

    [[signal takeLast:2] subscribeNext:^(id x) {
        //订阅信号,“2”代表取最后两次的信号,打印2,3
        NSLog(@"%@",x);
    }];

    [[signal skip:2] subscribeNext:^(id  _Nullable x) {
        //skip代表跳过信号,参数代表个数,跳过两个信号,打印3
        NSLog(@"%@",x);
    }];

2.映射(map&flatternMap)

//flattenMap和map的区别就是返回的是值还是信号
    [[self.userNameTF.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        //用户登录限制长度也可以用映射,把用户输入的字符串的信号转化成是否可以登录的信号
        return @(value.length > 11);
    }] subscribeNext:^(NSNumber  *_Nullable isLogin) {
        NSLog(@"%d",[isLogin boolValue]);
    }];
    //当就要映射信号的时候用flattenMap
    [self.userNameTF.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
       //需要返回信号
        return self.userNameTF.rac_textSignal;
    }];

3.合并

  • concat拼接
RACSignal *signle2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"3"];
        [subscriber sendNext:@"4"];
        [subscriber sendCompleted];
        return nil;
    }];

    [[signle1 concat:signle2] subscribeNext:^(id  _Nullable x) {
        //concat拼接功能,把signle1拼到signle2之前,按照顺序执行,打印1,2,3,4
        NSLog(@"%@",x);
    }];
  • merge&zip&combineLatest 组合
RACSignal *signle1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"1"];
        [subscriber sendNext:@"2"];
        [subscriber sendCompleted];
        return nil;
    }];

    RACSignal *signle2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"3"];
        [subscriber sendNext:@"4"];
        [subscriber sendCompleted];
        return nil;
    }];

    [[signle1 merge:signle2] subscribeNext:^(id  _Nullable x) {
        //merge,合并信号,当signle1和signle2任意一个发送,都会接收到,有点类似concat
        NSLog(@"%@",x);
    }];

    [[signle1 zipWith:signle2] subscribeNext:^(RACTuple  *_Nullable tuple) {
        //zip压缩信号,并把值也合并成元祖,但也是一个一个合并,所以会走两遍,1,3  2,4
        NSLog(@"%@--%@",tuple.first,tuple.second);
    }];

    [[signle1 combineLatestWith:signle2] subscribeNext:^(RACTuple *  _Nullable tuple) {
        //combineLatestWith也是合并信号,跟zip有点像,但是sigle1总会拿到最新的值才与signle2合并,打印 2,3  2,4
        NSLog(@"%@--%@",tuple.first,tuple.second);
    }];
  • then
RACSignal * signle = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"1"];
        [subscriber sendNext:@"2"];
        [subscriber sendCompleted];
        return nil;
    }];

    [[signle then:^RACSignal * _Nonnull{
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:@"3"];
            return nil;
        }];
    }] subscribeNext:^(id  _Nullable x) {
        //then会把之前的信号过滤掉,所以这里只会接收到第二个信号的值 3
        NSLog(@"%@",x);
    }];

    [signle subscribeNext:^(id  _Nullable x) {
        //第一个信号订阅了,所以顺序执行到这里才会打印1,2
        NSLog(@"%@",x);
    }];
  • delay&interval
[[RACSignal interval:5 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(NSDate * _Nullable x) {
        //定时,每个一段时间会调用,会把当前时间回调回来
        NSLog(@"%@",x);
    }];

    RACSignal *signle = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"1"];
        [subscriber sendCompleted];
        return nil;
    }];

    [[signle delay:5] subscribeNext:^(id  _Nullable x) {
      //延迟订阅
        NSLog(@"%@",x);
    }
时间: 2024-10-10 05:51:32

RAC基础笔记的相关文章

RAC基础笔记(2)

ReactiveCocoa 常见类 信号源相关 RACStream An abstract class representing any stream of values. RACStream 是一个抽象类,是以 Monad (函数式编程语言)的概念为依据进行设计的,它代表的就是一个 Monad .有了 Monad 作为基石后,许多基于流的操作就可以被建立起来了,比如map . filter . zip 等. RACSignal 可以把信号想象成水龙头,只不过里面不是水,而是玻璃球(value)

java String 类 基础笔记

字符串是一个特殊的对象. 字符串一旦初始化就不可以被改变. String s = "abc";//存放于字符串常量池,产生1个对象 String s1=new String("abc");//堆内存中new创建了一个String对象,产生2个对象 String类中的equals比较字符串中的内容. 常用方法: 一:获取 1.获取字符串中字符的个数(长度):length();方法. 2.根据位置获取字符:charAt(int index); 3.根据字符获取在字符串中

网络基础笔记——OSI七层模型

OSI七层模型 由于整个网络连接的过程相当复杂,包括硬件.软件数据封包与应用程序的互相链接等等.如果想要写一支将联网全部功能都串连在一块的程序,那么当某个小环节出现问题时,整只程序都需要改写.所以我们将整个网络分成数层,每层都有自己独立的功能,而且每层的代码都可以独立撰写,因为相互之间不会干扰.如此一来,当某个小环节出现问题时,只要将该层的代码改写即可.并且这样可以让整个网络层次更加的清晰. 在网络上传输信息就像是一个发包裹的过程,从己方的应用程序开始往第七层的包裹里塞数据,再依次塞到第一层的包

[Java基础笔记]数组

Java基础笔记 定义数组: int[] numbers = new int[100]; //方法一 double[] num = new double[10]; int[][] a = new int[2][5]; 通过new创建的数组,元素默认值为0(0.0) int[] scores = {5,4,33,12,46}; //方法二 int[][] a = { //位数不足,自动补0 {5,3,2,1,6}, {10,12,14,15}, }; 数组特性:存储的都是同类型数据:长度定义后不可

C# 基础笔记(第一篇)

C#基础 概念:.net与c#.net/dontnet:一般指.net framework框架,一种平台,一种技术c#(charp):一种编程语言,可以开发基于.net的应用. *java既是一种技术又是一种编程语言.                           .net都能干什么?开发桌面应用程序   Winforminternet应用程序    Asp.net/webservice C/S:客户机(Client)/服务器模式(Server)B/S:浏览器(Browser)/务器模式(

我的LINUX基础笔记

Linux系统管理      1 Day   2014.5.23 su -name   切换用户passwd 密码   更改密码gnome-terminal    伪CLI   桌面终端程序1.查看内核版本uname -r    2.查看红帽系统版本cat /etc/redhat-rdlease3.查看LINUX标准分发版信息  lsb_release4.查看网卡的IP,MAX       ifconfig                       ifconfig eth 10.0.0.10

Nginx基础笔记

Nginx基础笔记 资源 安装 ubuntu下 编译安装 基本操作 HTTP基本配置 配置说明 配置文件目录结构 配置文件结构 模块 模块化 index模块 Log模块 Real IP模块 Access模块 Rewrite模块 Proxy模块 upstream模块 其他 配置静态化目录 负载均衡 控制页面缓存 nginx的内置变量 nginx小结 资源 资源 Nginx 官网 Nginx 官方下载地址 Nginx最佳实践配置项目 地址 Nginx Configuration wiki 教程 ag

MYSQL基础笔记(三)-表操作基础

数据表的操作 表与字段是密不可分的. 新增数据表 1 Create table [if not exists] 表名( 2 字段名 数据类型, 3 字段名 数据类型, 4 字段n 数据类型 --最后一行不需要加逗号 5 )[表选项]; If not exists:如果表名不存在,那么就创建,否则不执行创建代码,实现检查功能. 表选项:控制表的表现 1.字符集:charset/character 具体字符集:--保证表中数据存储的字符集. 2.校对集:collate 具体校对集: 3.存储引擎:e

REDIS基础笔记

Redis基础笔记 资源链接 简介 简介 安装 五种数据类型及相应命令 1. 字符串类型 2. 散列类型 3. 列表类型 4. 集合类型 5. 有序集合 其他 事务 SORT 生存时间 任务队列 发布/订阅模式 Python中使用Redis 实际实例 管理 其他 资源链接 推荐书籍:<Redis入门指南> 资源列表: redis命令速查command | CMD索引-中文 | CMD树-中文 redis源码github 下载地址redis.io The Little Redis book 入口