导入ReactiveCocoa框架
  • 在终端,进入Reactive Cocoa文件下
  • 创建podfile
  • 打开该文件
  • 并配置
    • use_frameworks!
    • pod ’ReactiveCocoa’, ’~>4.0.2-alpha-1'
  • 安装pod install --no-repo-update
  • 遇到头文件导入不进去,可以将头文件放到全局的.h文件中
 
 
ReactiveCocoa常见的类
  1. RACSignal:信号类;RACSubscriber是协议
  • 简介

    • 有数据产生时就会使用RACSignal类
    • 默认是冷信号,必须订阅信号类
  • RACSignal使用步骤
    • 创建信号(默认创建的是冷信号)

      • didSubscribe调用:只要一个信号被订阅就会调用
      • didSubscribe作用:发送数据
    • 订阅信号(变为热信号)subscribeNext:订阅
      • nextBlock调用:只要订阅者发送数据就会调用
      • nextBlock作用:处理数据,展示在UI上面
    • 发送信号(sendNext:)
只要订阅者调用sendNext就会执行nextBlock
只要订阅RACDynamicSignal就会执行didSubscribe
前提条件是RACDynamicSignal,不同类型信号的订阅,处理订阅的事情不一样
 
RACSignal使用步骤:
 1.创建信号 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
 2.订阅信号,才会激活信号. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
 3.发送信号 - (void)sendNext:(id)value

 RACSignal底层实现:
 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
 2.2 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
 2.1 subscribeNext内部会调用siganl的didSubscribe
 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
 3.1 sendNext底层其实就是执行subscriber的nextBlock

// 1.创建信号
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
   
    // block调用时刻:每当有订阅者订阅信号,就会调用block。
   
    // 2.发送信号
    [subscriber sendNext:@1];
   
    // 如果不在发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
    [subscriber sendCompleted];
   
    return [RACDisposable disposableWithBlock:^{
       
        // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
       
        // 执行完Block后,当前信号就不在被订阅了。
       
        NSLog(@"信号被销毁");
       
    }];
}];

// 3.订阅信号,才会激活信号.
[siganl subscribeNext:^(id x) {
    // block调用时刻:每当有信号发出数据,就会调用block.
    NSLog(@"接收到数据:%@",x);
}];
 
     2.  RACDisposable:取消订阅
  • 只要信号发送数据完毕就会自动取消订阅
  • 只要订阅者在就不会自动取消信号的订阅
    • 调用[disposable dispose];就会取消
 
 
     3.  RACSubject:信号提供者,自己可以充当信号,也可以充当订阅者
  • 必须先订阅再发送信号
  • 使用场景: 通常用来代替代理,有了他就不必定义代理了
  • RACSubject使用步骤
     1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
     2.订阅信号 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
     3.发送信号 sendNext:(id)value
  • RACSubject:底层实现和RACSignal不一样。
     1.调用subscribeNext订阅信号,只是把订阅者保存起来,并且订阅者的nextBlock已经赋值了。
     2.调用sendNext发送信号,遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
       
    // 1.创建信号
    RACSubject *subject = [RACSubject subject];

    // 2.订阅信号
    [subject subscribeNext:^(id x) {
        // block调用时刻:当信号发出新值,就会调用.
        NSLog(@"第一个订阅者%@",x);
    }];
    [subject subscribeNext:^(id x) {
        // block调用时刻:当信号发出新值,就会调用.
        NSLog(@"第二个订阅者%@",x);
    }];

    // 3.发送信号
    [subject sendNext:@"1"];
 
     4.  RACReplaySubject: 重复提供信号类,是RACSubject的子类
      RACReplaySubject可以先发送信号,在订阅信号,RACSubject就不可以。
     使用场景一`:如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。
     使用场景二`:可以设置capacity数量来限制缓存的value的数量,即只缓充最新的几个值。
  • RACReplaySubject使用步骤:
     1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
     2.可以先订阅信号,也可以先发送信号。
       2.1 订阅信号 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
       2.2 发送信号 sendNext:(id)value
  • RACReplaySubject:底层实现和RACSubject不一样。
     1.调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
     2.调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock
  • 如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。也就是先保存值,在订阅值。
       
    // 1.创建信号
    RACReplaySubject *replaySubject = [RACReplaySubject subject];

    // 2.发送信号
    [replaySubject sendNext:@1];
    [replaySubject sendNext:@2];

    // 3.订阅信号
    [replaySubject subscribeNext:^(id x) {
       
        NSLog(@"第一个订阅者接收到的数据%@",x);
    }];

    // 订阅信号
    [replaySubject subscribeNext:^(id x) {
       
        NSLog(@"第二个订阅者接收到的数据%@",x);
    }];
 
>>> RACSubject替换代理
      需求:
1.给当前控制器添加一个按钮,modal到另一个控制器界面
2.另一个控制器view中有个按钮,点击按钮,通知当前控制器
      步骤一:在第二个控制器.h,添加一个RACSubject代替代理。
@interface TwoViewController : UIViewController

@property (nonatomic, strong) RACSubject *delegateSignal;

@end

步骤二:监听第二个控制器按钮点击
@implementation TwoViewController
- (IBAction)notice:(id)sender {
    // 通知第一个控制器,告诉它,按钮被点了

     // 通知代理
     // 判断代理信号是否有值
    if (self.delegateSignal) {
        // 有值,才需要通知
        [self.delegateSignal sendNext:nil];
    }
}
@end

步骤三:在第一个控制器中,监听跳转按钮,给第二个控制器的代理信号赋值,并且监听.
@implementation OneViewController
- (IBAction)btnClick:(id)sender {

    // 创建第二个控制器
    TwoViewController *twoVc = [[TwoViewController alloc] init];

    // 设置代理信号
    twoVc.delegateSignal = [RACSubject subject];

    // 订阅代理信号
    [twoVc.delegateSignal subscribeNext:^(id x) {

        NSLog(@"点击了通知按钮");
    }];

    // 跳转到第二个控制器
    [self presentViewController:twoVc animated:YES completion:nil];

}
@end
    
 
 
     5.  RACTuple: 元组类
          RACSequence:集合类,用于代替NSArray,NSDictionary,可以用来快速遍历数组和字典
// 1.遍历数组
NSArray *numbers = @[@1,@2,@3,@4];

// 这里其实是三步
// 第一步: 把数组转换成集合RACSequence numbers.rac_sequence
// 第二步: 把集合RACSequence转换RACSignal信号类,numbers.rac_sequence.signal
// 第三步: 订阅信号,激活信号,会自动把集合中的所有值,遍历出来。
[numbers.rac_sequence.signal subscribeNext:^(id x) {
    NSLog(@"%@",x);
}];

// 2.遍历字典,遍历出来的键值对会包装成RACTuple(元组对象)
NSDictionary *dict = @{@"name":@"HMJ",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
   
    // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
    RACTupleUnpack(NSString *key, NSString *value) = x;
   
    // 相当于以下写法
    //        NSString *key = x[0];
    //        NSString *value = x[1];
   
    NSLog(@"%@ %@",key,value);
}];

3.字典转模型
3.1 OC写法
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];

NSMutableArray *items = [NSMutableArray array];

for (NSDictionary *dict in dictArr) {
    FlagItem *item = [FlagItem flagWithDict:dict];
    [items addObject:item];
}

3.2 RAC写法
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];

NSMutableArray *flags = [NSMutableArray array];

_flags = flags;

// rac_sequence注意点:调用subscribeNext,并不会马上执行nextBlock,而是会等一会。
[dictArr.rac_sequence.signal subscribeNext:^(id x) {
    // 运用RAC遍历字典,x:字典
   
    FlagItem *item = [FlagItem flagWithDict:x];
   
    [flags addObject:item];
   
}];

NSLog(@"%@",  NSStringFromCGRect([UIScreen mainScreen].bounds));

 
3.3 RAC高级写法:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
// map:映射的意思,目的:把原始值value映射成一个新值
// array: 把集合转换成数组
// 底层实现:当信号被订阅,会遍历集合中的原始值,映射成新值,并且保存到新的数组里。
NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {
   
    return [FlagItem flagWithDict:value];
   
}] array];
 
 
 
 
 
 
 
 

RAC(Reactive Cocoa)常见的类的更多相关文章

  1. [HMLY]9.深入浅出-iOS Reactive Cocoa的常见用法

    简介 今天的主角是Reactive Cocoa,聊聊Reactive Cocoa的常见使用:KVO.Target.Delegate.Notification. Reactive Cocoa 是一个重量 ...

  2. iOS-Reactive Cocoa的常见用法

    今天是周末,临近年底,工作上遇到不可抗力,会有点一些变动!这多少会让人有一点静不下来,但需克制,Reactive Cocoa是今天的主角! 废话不多说,今天聊聊Reactive Cocoa的常见使用! ...

  3. iOS开发之OC篇-响应式编程Reactive Cocoa

    一.Reactive Cocoa 介绍 Reactive Cocoa 是 iOS 开发的一个 "重量级" 框架 高大上的概念:响应式编程 核心概念:信号 Signal 官方网站:h ...

  4. Android 常见工具类封装

    1,MD5工具类: public class MD5Util { public final static String MD5(String s) { char hexDigits[] = { '0' ...

  5. Hibernate api 之常见的类(配置类,会话工厂类,会话类)

    1:Configuration :配置管理类对象 1.1:config.configure(): 加载主配置文件的方法(hibernate.cfg.xml) ,默认加载src/hibernate.cf ...

  6. Cocoa对象——根类

    [转载自:http://mobile.51cto.com/iphone-274229.htm] Cocoa对象 根类是本文要介绍的内容,仅凭Objective-C语言和运行环境并不足以构造哪怕是最简单 ...

  7. Selenium常见报错问题(1)- 先来认识下selenium常见异常类

    如果你在跑selenium脚本时,需要某些异常不知道怎么解决时,可以看看这一系列的文章,看看有没有你需要的答案 https://www.cnblogs.com/poloyy/category/1749 ...

  8. Swift快速给Cocoa库内置类添加便捷初始化器

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) Cocoa中的NSShadow类默认没有我们需要的实例方法,为 ...

  9. Why Reactive(Cocoa)?-时间线、输入、输出、复杂性、异步、状态、聚合

    To put it another way, the output at any one time is the result of combining all inputs. The output ...

随机推荐

  1. MapReduce Service更换集群外部时钟源,仅需10步

    摘要:MapReduce Service 集群使用NTP进行时钟同步.本文简要介绍了MapReduce Service集群NTP机制及NTP的配置方式. 本文分享自华为云社区<MapReduce ...

  2. JMeter学习笔记--函数学习(_csvRead 函数)

    JMeter函数可以很方便实现一些小功能,几乎可以用于测试计划中的任何元件.一个函数的调用如下:${_functionName(var1,var2,var3)},_functionName匹配函数名, ...

  3. Win10-更改c盘下的用户文件夹名

    如果你是win10家庭版,请先升级成专业版 win10家庭版升级到win10专业版 修改用户名称

  4. Linux USB (目录)

    1.USB 总线简介 2.USB 协议分析 3.USB Host 详解 4.USB Device 详解 5.usbip (USB Over IP) 使用实例

  5. 2021 陇剑杯wp

    前言 这比赛应该叫应急响应比赛,而且flag交三次就不能交了,就因为我交错一道题然后差一道进线下,气死了. Jwt 2.1 jwt 题目提示 2.2 搜索username得到 10087#admin ...

  6. c++学习笔记(七)

    位运算和sizeof运算符 位运算 C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的. 位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果. ...

  7. 问题 A: 大数阶乘

    题目描述 我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,我们该如何去计算它并输出它? 输入 输入一个整数m(0<m<=5000) 输出 输出m的阶乘,并在输出结束之后输入一个换行 ...

  8. Spring Boot 2.6.0正式发布:默认禁止循环依赖、增强Docker镜像构建...

    昨天,Spring官方正式发布了Spring Boot今年最后一个特性版本:2.6.0 同时,也宣布了2.4.x版本的终结. 那么这个新版本又带来了哪些新特性呢?下面就一起跟着DD来看看吧! 重要特性 ...

  9. [luogu5666]树的重心

    考虑枚举一个点k,求其为重心的方案数暴力的做法是,将其作为根搜索,设最大子树大小为s1,次大为s2,对割掉的子树分类讨论:1.在子树中,分两种情况(都可以用线段树合并来做) (1)从s1中切掉一棵大小 ...

  10. opencv 视频处理相关

    包含视频格式知识(编解码和封装格式):如何获取视频信息及视频编解码格式:opencv读取及保存视频,及opencv fourcc编码格式 一.基础知识 视频的编解码格式和封装格式 参考如山似水 视频编 ...