详解如何使用ReactiveObjC

概述

RAC架构框架图

信号流程

基本使用

1、基本控件

UITextField

//监听文本输入
 [[_textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@",x);
 }];

//可根据自己想要监听的事件选择
 [[_textField rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(__kindof UIControl * _Nullable x) {
     NSLog(@"%@",x);
 }];
//添加条件 -- 下面表示输入文字长度 > 10 时才会调用subscribeNext
 [[_textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
     return value.length > 10;
 }] subscribeNext:^(NSString * _Nullable x) {
     NSLog(@"输入框内容:%@", x); }];

UIButton

//监听按钮点击事件
[[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        NSLog(@"-->%@",x);
}];

计时器(interval、delay)

//类似timer
@weakify(self)
self.disposable = [[RACSignal interval:2 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {
        @strongify(self)
        NSLog(@"时间:%@", x); // x 是当前的时间
        //关闭计时器
        [self.disposable dispose];
}];
//延时
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"延时2秒"];
        return nil;<br>}] delay:2] subscribeNext:^(id x) {

        NSLog(@"-->%@",x);
}];

2、监听属性变化

//监听self的name属性
[RACObserve(self, name) subscribeNext:^(id  _Nullable x) {
        NSLog(@"属性的改变-->%@",x);
}];
[[self rac_valuesForKeyPath:@"name" observer:self] subscribeNext:^(id  _Nullable x) {
        NSLog(@"属性的改变-->%@", x);
}];
//此处RAC宏相当于让_label订阅了_textField的文本变化信号
//赋值给label的text属性
RAC(_label, text) = _textField.rac_textSignal;

3、遍历数组和字典

//遍历数组
 NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
[array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
      NSLog(@"内容-->%@", x)<br>}];

4、监听 Notification 通知事件

[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"notification" object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"-->%@", x);
}];

5、代替Delegate代理

//监听按钮点击方法的信号
//当执行完btnClickAction后会执行此订阅
[[self rac_signalForSelector:@selector(btnClickAction:)] subscribeNext:^(RACTuple * _Nullable x) {
        NSLog(@"-->%@", x);
}];
-(void) btnClickAction:(UIButton *)btn
{
    NSLog(@"按钮点击");
}

二、RAC常用类

RACSignal

RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
      [subscriber sendNext:@"🍺🍺🍺🍺🍺🍺🍺"];
      [subscriber sendCompleted];
      return [RACDisposable disposableWithBlock:^{
          NSLog(@"销毁了🍺🍺🍺");
      }];
  }];
  [signal subscribeNext:^(id  _Nullable x) {
      NSLog(@"%@",x);
  }];

RACSubject(可发送信号也可以订阅信号)

RACTuple(元组)-- 其内部就是封装了数组,用起来跟数组差不多

//通过定值创建RACTuple
RACTuple *tuple = [RACTuple tupleWithObjects:@"1", @"2", @"3", nil];
//利用 RAC 宏快速封装
RACTuple *tuple2 = RACTuplePack(@"1", @"2", @"3");
//从别的数组中获取内容
RACTuple *tuple3 = [RACTuple tupleWithObjectsFromArray:@[@"1", @"2", @"3"]];

NSLog(@"元组-->%@", tuple3[0]);
NSLog(@"第一个元素-->%@", [tuple3 first]);
NSLog(@"最后一个元素-->%@", [tuple3 last]);

RACMulticastConnection -- 用于当一个信号,被多次订阅时,为了保证创建信号时,避免多次调用创建信号中的block

RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
       [subscriber sendNext:@"signal1-->🍺🍺🍺🍺🍺🍺🍺"];
       [subscriber sendCompleted];
       return [RACDisposable disposableWithBlock:^{
           NSLog(@"signal1销毁了");
       }];
   }];

   RACMulticastConnection *connection = [signal1 publish];

   [connection.signal subscribeNext:^(id  _Nullable x) {
       NSLog(@"subscribeNext-->1");
   }];
   [connection.signal subscribeNext:^(id  _Nullable x) {
       NSLog(@"subscribeNext-->2");
   }];
   [connection.signal subscribeNext:^(id  _Nullable x) {
       NSLog(@"subscribeNext-->3");
   }];
   [connection connect];

RACCommand -- 可以监听信号的状态等

NSString *input = @"执行";
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
    NSLog(@"input-->%@",input);
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"🍺🍺🍺🍺🍺🍺🍺"];
        [subscriber sendError:[NSError errorWithDomain:@"error" code:-1 userInfo:nil]];
//            [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{
            NSLog(@"signal销毁了");
        }];
    }];
}];
[command.executionSignals subscribeNext:^(RACSignal   * _Nullable x) {
    NSLog(@"executionSignals-->%@",x);
    [x subscribeNext:^(id  _Nullable x) {
        NSLog(@"executionSignals-->subscribeNext-->%@",x);
    }];
}];
[[command.executionSignals switchToLatest] subscribeNext:^(id  _Nullable x) {
    NSLog(@"switchToLatest-->%@",x);
}];
[command.executing subscribeNext:^(id  _Nullable x) {
    NSLog(@"executing-->%@",x);
}];
[command.errors subscribeNext:^(id  _Nullable x) {
    NSLog(@"errors-->%@",x);
}];
//开始执行
[command execute:input];

三、高级函数使用

1、连接信号、合并信号等

首先创建两个信号signal1和signal2来演示

RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
     [subscriber sendNext:@"signal1-->🍺🍺🍺🍺🍺🍺🍺"];
     [subscriber sendCompleted];
     return [RACDisposable disposableWithBlock:^{
         NSLog(@"signal1销毁了");
     }];
 }];
 RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
     [subscriber sendNext:@"signal2-->🍺🍺🍺🍺🍺🍺🍺"];
     [subscriber sendCompleted];
     return [RACDisposable disposableWithBlock:^{
         NSLog(@"signal2销毁了");
     }];
 }];

1.1、 concat -- 当多个信号发出的时候,有顺序的接收信号

一个信号signal3去监听signal1和signal2,必须是接收signal1完后才会接收signal2

RACSignal *signal3 = [signal1 concat:signal2];
  [signal3 subscribeNext:^(id  _Nullable x) {
      NSLog(@"signal3-->%@",x);
  }];

1.2、 combineLatestWith -- 将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号(订阅者每次接收的参数都是所有信号的最新值),不论触发哪个信号都会触发合并的信号

一个信号signal3去监听signal1和signal2,每次回调两个信号的最新值

RACSignal *signal3 = [signal1 combineLatestWith:signal2];
   [signal3 subscribeNext:^(id  _Nullable x) {
       NSLog(@"%@",x);
   }];

PS:注释signal1的sendNext方法,直接销毁了,所以每个singal必须有sendNext方法

1.3、 then -- 用于连接两个信号,等待第一个信号完成,才会连接then返回的信号

RACSignal *signal3 = [signal1 then:^RACSignal * _Nonnull{
    return signal2;
}];
[signal3 subscribeNext:^(id  _Nullable x) {
    NSLog(@"signal3-->%@",x);
}];

1.4、 merge -- 把多个信号合并为一个信号来监听,任何一个信号有新值的时候就会调用

一个信号signal3去监听signal1和signal2,每次回调一个信号

RACSignal *signal3 = [signal1 merge:signal2];
[signal3 subscribeNext:^(id  _Nullable x) {
    NSLog(@"signal3-->%@",x);
}];

1.5、 zipWith -- 把两个信号压缩成一个信号,只有当两个信号都发出信号内容时,才会触发

一个信号signal3去监听signal1和signal2,但必须两个信号都有发出(不需要同时,例如signal1信号发出了,signal2信号等了10秒之后发出,那么signal3的订阅回调是等signal2信号发出的那一刻触发)

RACSignal *signal3 = [signal1 zipWith:signal2];
[signal3 subscribeNext:^(id  _Nullable x) {
    NSLog(@"signal3-->%@",x);
}];

1.6、 reduce 聚合 -- 把多个信号的值按照自定义的组合返回

RACSignal *signal3 = [RACSignal combineLatest:@[signal1,signal2] reduce:^id(NSString *s1 ,NSString *s2){
    return [NSString stringWithFormat:@"%@ %@",s1,s2];
}];
[signal3 subscribeNext:^(id x) {
    NSLog(@"%@",x);
}];

2、flattenMap & map 映射

flattenMap 的底层实现是通过bind实现的

map 的底层实现是通过 flattenMap 实现的

//map事例
[[_textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        return [NSString stringWithFormat:@"%@🍺🍺🍺🍺🍺🍺🍺",value];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"-->%@",x);
    }] ;
//flattenMap事例
 [[_textField.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:[NSString stringWithFormat:@"%@🍺🍺🍺🍺🍺🍺🍺",value]];
            [subscriber sendCompleted];
            return [RACDisposable disposableWithBlock:^(){}];
        }];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"-->%@",x);
    }] ;

3、filter -- 过滤、ignore -- 忽略、distinctUntilChanged -- 忽略相同

filter、ignore

//map事例
[[_textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        return [NSString stringWithFormat:@"%@🍺🍺🍺🍺🍺🍺🍺",value];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"-->%@",x);
    }] ;
//flattenMap事例
 [[_textField.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:[NSString stringWithFormat:@"%@🍺🍺🍺🍺🍺🍺🍺",value]];
            [subscriber sendCompleted];
            return [RACDisposable disposableWithBlock:^(){}];
        }];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"-->%@",x);
    }] ;

distinctUntilChanged

RACSubject *subject = [RACSubject subject];
   [[subject distinctUntilChanged] subscribeNext:^(id  _Nullable x) {
       NSLog(@"-->%@",x);
   }];
   [subject sendNext:@"123"];
   [subject sendNext:@"123"];
   [subject sendNext:@"123"];
   [subject sendNext:@"🍺🍺🍺🍺🍺🍺"];
   [subject sendNext:@"🍺🍺🍺🍺🍺🍺"];
   [subject sendCompleted];

以上就是详解如何使用ReactiveObjC的详细内容,更多关于如何使用ReactiveObjC的资料请关注我们其它相关文章!

(0)

相关推荐

  • 如何在IOS中使用IBeacon

    什么是iBeacon? iBeacon 是苹果公司2013年9月发布的移动设备用OS(iOS7)上配备的新功能.其工作方式是,配备有低功耗蓝牙(BLE)通信功能的设备使用BLE技术向周围发送自己特有的 ID,接收到该 ID 的应用软件会根据该 ID 采取一些行动. 从个人的角度看: iBeacon向四面八方不停地广播信号,就像是往平静的水面上扔了一块石子,泛起层层涟漪(俗称水波),波峰相当于 iBeacon 的RSSI(接受信号强度指示),越靠近中心点的地方波峰越高(RSSI 越大),这个波峰的

  • iOS实现循环滚动公告栏

    本文实例为大家分享了iOS实现循环滚动公告栏的具体代码,供大家参考,具体内容如下 封装了一个继承于UIView的类,如下: #import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface XtayNoticeScrollView : UIView - (instancetype)initWithFrame:(CGRect)frame titleArray:(NSArray<NSString *> *)titleArray; -

  • 如何在IOS中使用Cordova插件

    一.准备 插件功能:打开IOS相机 1:创建插件 plugman create --name [插件名称] --plugin_id [插件ID] --plugin_version [插件版本号] plugman create --name CameraDemo --plugin_id cordova-plugin-camerademo --plugin_version 1.0.0 2:添加IOS平台 plugman platform add --platform_name ios 3:创建pac

  • iOS tableView多输入框如何获取数据

    前言 难得有点空暇的时间,写写文章,一壶小茶,惬意.扯远了,言归正传. 大家在做App开发的时候,肯定遇到过在一个列表中有多个让用户填写资料的情况,类似于这样的界面: iOS 如果一个tableView中有很多的输入框,而且cell是复用的,这个还有个提交功能 我的设计思路是这样的 1.建立一个Model对象,包含要输入的所有字段, 2.在建立一个cell,有个label和textField, 3.在初始化cell的地方,根据不同的indexRow,显示cell上不同的label,例如昵称.邮箱

  • iOS给border设置渐变色的方法实例

    前言 本文将从4行代码出发给一个view设置渐变色,分别会谈到几个重要的渐变色相关属性,在使用过程中有几个需要特别关注的点. 给一个view的border设置渐变色是比较高阶的用法,希望本文可以在这个方面帮助到你. 给view设置渐变色 通过4行代码就可以给一个view设置渐变色: let view = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100)) let gradientLayer = CAGradientLaye

  • 详解 iOS 系统中的视图动画

    动画为用户界面的状态转换提供了流畅的可视化效果, 在 iOS 中大量使用了动画效果, 包括改变视图位置. 大小. 从可视化树中删除视图, 隐藏视图等. 你可以考虑用动画效果给用户提供反馈或者用来实现有趣的特效. 在 iOS 系统中, Core Animation 提供了内置的动画支持, 创建动画不需要任何绘图的代码, 你要做的只是激发指定的动画, 接下来就交给 Core Animation 来渲染, 总之, 复杂的动画只需要几行代码就可以了. 哪些属性可以添加动画效果 根据 iOS 视图编程指南

  • 详解IOS判断当前网络状态的三种方法

    在项目中,为了好的用户体验,有些场景必须线判断网络状态,然后才能决定该干嘛.比如视频播放,需要线判断是Wifi还是4G,Wifi直接播放,4G先提示用户.获取网络状态的方法大概有三种: 1. Reachability 这是苹果的官方演示demo中使用到的方法,我们可以到苹果官方文档里下载Demo(点击左上角Download Sample Code 即可下载),然后把Demo里的Reachability.h和.m考到自己项目中,并在Build Phases 的 Link Binary 添加Syst

  • iOS UIBezierPath实现饼状图

    本文实例为大家分享了iOS UIBezierPath实现饼状图的具体代码,供大家参考,具体内容如下 首先看效果图: 代码: #import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface CircleView : UIView @property (nonatomic, copy) NSArray<NSNumber *> *valueArray; @end NS_ASSUME_NONNULL_END // #define S_W

  • IOS接入facebook详解

    facebook 接入 1.在 facebook 后台 配置 ios 平台, 获取 fb appid store id 可以先随便找一个已存在的填入进去. 2.CocoaPods 引入几个核心库 pod 'FBSDKCoreKit', '~> 9.0.1' pod 'FBSDKLoginKit', '~> 9.0.1' pod 'FBSDKShareKit', '~> 9.0.1' pod 工程构建出 静态库丢到 /Users/XXX/Library/Developer/Xcode/De

  • 详解如何使用ReactiveObjC

    概述 RAC架构框架图 信号流程 基本使用 1.基本控件 UITextField //监听文本输入 [[_textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) { NSLog(@"%@",x); }]; //可根据自己想要监听的事件选择 [[_textField rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(_

  • AngularJS 日期格式化详解

    AngularJS是为了克服HTML在构建应用上的不足而设计的.HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了.所以我做了一些工作(你也可以觉得是小花招)来让浏览器做我想要的事. AngularJS的日期格式化有两种形式,一种是在HTML页面,一种是在JS代码里,都是用到AngularJS的过滤器$filter. HTML: date_expression 即 你在$scope中设的date类型变量(注意,一定是date object才正确), 也是要显

  • spring boot的maven配置依赖详解

    本文介绍了spring boot的maven配置依赖详解,分享给大家,具体如下: 我们通过引用spring-boot-starter-parent,添加spring-boot-starter-web 可以实现web项目的功能,当然不使用spring-boot-start-web,通过自己添加的依赖包也可以实现,但是需要一个个添加,费时费力,而且可能产生版本依赖冲突.我们来看下springboot的依赖配置: 利用pom的继承,一处声明,处处使用.在最顶级的spring-boot-dependen

  • 基于ES6作用域和解构赋值详解

    ES6 强制开启严格模式 作用域 •var 声明局部变量,for/if花括号中定义的变量在花括号外也可访问 •let 声明的变量为块作用域,变量不可重复定义 •const 声明常量,块作用域,声明时必须赋值,不可修改 // const声明的k指向一个对象,k本身不可变,但对象可变 function test() { const k={ a:1 } k.b=3; console.log(k); } test()解构赋值 { let a, b, 3, rest; [a, b, c=3]=[1, 2]

  • [译]ASP.NET Core 2.0 路由引擎详解

    本文介绍了ASP.NET Core 2.0 路由引擎详解,分享给大家,具体如下: 问题 ASP.NET Core 2.0的路由引擎是如何工作的? 答案 创建一个空项目,为Startup类添加MVC服务和请求中间件: public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvir

  • Asp.net MVC scheduler的实现方法详解

    Asp.net MVC scheduler的实现方法详解 本例使用了fullcalendar js : https://fullcalendar.io/ 1. view : @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } @section PageContent{ <style> .modal-backdrop { z-index: 9; } </sty

  • 关于日期正则表达式的思路详解

    1        概述 首先需要说明的一点,无论是Winform,还是Webform,都有很成熟的日历控件,无论从易用性还是可扩展性上看,日期的选择和校验还是用日历控件来实现比较好. 前几天在CSDN多个版块看到需要日期正则的帖子,所以整理了这篇文章,和大家一起讨论交流,如有遗漏或错误的地方,还请大家指正. 日期正则一般是对格式有要求,且数据不是直接由用户输入时使用.因应用场景的不同,写出的正则也不同,复杂程度也自然不同.正则的书写需要根据具体情况具体分析,一个基本原则就是:只写合适的,不写复杂

  • 关于正则表达式基本语法的应用详解(必看篇)

    1.正则表达式基本语法 两个特殊的符号'^'和'$'.他们的作用是分别指出一个字符串的开始和结束.例子如下: "^The":表示所有以"The"开始的字符串("There","The cat"等): "of despair$":表示所以以"of despair"结尾的字符串: "^abc$":表示开始和结尾都是"abc"的字符串--呵呵,只有&qu

  • mysql 5.7.20解压版安装方法步骤详解(两种方法)

    我来讲解下window64位下MySQL的安装,MySQL是在5.7开始安装版就只有32位下载服务了,这里我讲解解压版的MySQL如何安装,在安装MySQL解压版时对于新手的小编来说也是头疼得很,各种问题各种来没有安装版的一键轻松搞定的方便,安装时需要注意三点:1.路径配置,2.安装时MySQL端口被占用这时需要关闭被占用端口,3.cmd必须是在管理员环境下设置MySQL信息. MySQL官网: https://www.mysql.com/downloads/ http://www.jb51.n

  • Mac OS系统下mysql 5.7.20安装教程图文详解

    Mac OS X 下 TAR.GZ 方式安装 MySQL 5.7 与 MySQL 5.6 相比, 5.7 版本在安装时有两处不同: 1:初始化方式改变, 从scripts/mysql_install_db --user=mysql初始化方式变成了bin/mysqld --initialize --user=mysql方式; 2: 初始密码生成改变, 5.6 的版本在 tar gz 方式初始化完成后默认 root 密码为空, 5.7 版本在初始化完成后会生成一个临时的 root 密码: 一.在浏览

随机推荐