一 导入ReactiveCocoa框架

通常都会使用CocoaPods(用于管理第三方框架的插件)帮助我们导入

podfile如果只描述pod 'ReactiveCocoa', '~> 4.0.2-alpha-1',会导入不成功 因为用到了swift的一些东西 需要在podfile加上use_frameworks,重新pod install 才能导入成功

ReactiveCocoa常见的一些类: RACSignal:信号类,一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据。 1.信号类(RACSiganl),只是表示当数据改变时,信号内部会发出数据,它本身不具备发送信号的能力,而是交给内部一个订阅者去发出 2.默认一个信号都是冷信号,也就是值改变了,也不会触发,只有订阅了这个信号,这个信号才会变为热信号,值改变了才会触发。 3.如何订阅信号:调用信号RACSignal的subscribeNext就能订阅 简单使用: // 1.创建信号 RACSubscriber是订阅者 RACSignal racsignal = [RACSignal createSignal:^RACDisposable (id subscriber) { // 3.发送信号 [subscriber sendNext:@100]; return nil; }];

   //  2.订阅信号
[racsignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];

RACSubscriber:表示订阅者的意思用于发送一个信号,这是一个协议,不是一个类,只要遵守这个协议并且实现方法才能成为订阅者,通过create创建信号,都有一个订阅者,帮助他发送数据 RACDisposable:用于取消订阅者或者清理资源,当信号发送完成或者发送错误的时候就会自动触发取消订阅 使用场景:不想监听某个信号时候可以用他主动取消订阅信号 例如:

// 1.创建信号 RACSignal racsignal = [RACSignal createSignal:^RACDisposable (id subscriber) { // 3.发送信号 [subscriber sendNext:@100];

  // 订阅者subscriber不会被销毁永远不会取消订阅(在不主动取消的情况下)
_subscriber = subscriber;// _subscriber成员变量强引用一次
self.disposable = [RACDisposable disposableWithBlock:^{
NSLog(@"信号被取消订阅");
}];
return self.disposable;

}]; // 2.订阅信号 subscribeNext在函数内部创建订阅者 [racsignal subscribeNext:^(id x) { NSLog(@"%@",x); }];

// 取消订阅
[self.disposable dispose];

RACSubject:信号提供者,自己可以充当信号又可以发送信号 使用场景,通常用来代替代理,有了它就可以不用定义代理了。 RACReplaySubject:重复提供信号类 RACSubject的子类 RACReplaySubject和RACSubject的区别: RACReplaySubject可以先发送信号在订阅信号,RACSubject不可以。

RACSubject使用步骤: // 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block RACSubject *subject = [RACSubject subject];

// 2.订阅信号 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
// 返回的是订阅者

RACDisposable posable1 = [subject subscribeNext:^(id x) { NSLog(@"第一个订阅者%@",x); }]; RACDisposableposable2 = [subject subscribeNext:^(id x) { NSLog(@"第二个订阅者%@",x); }];

// RACSubject:底层实现和RACSignal不一样。
// 1.调用subscribeNext订阅信号,只是把订阅者保存起来,并且订阅者的nextBlock已经赋值了。
// 2.调用sendNext发送信号,遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。 //3.发送信号 sendNext:(id)value
[subject sendNext:@100];
[posable1 dispose];// 取消订阅信号
[subject sendNext:@100];

RACReplaySubject:使用步骤 RACReplaySubject *subjest = [RACReplaySubject subject];

//2.调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock
RACDisposable *posable1 = [subjest subscribeNext:^(id x) {
NSLog(@"第一个订阅者%@",x);
}]; RACDisposable *posable2 = [subjest subscribeNext:^(id x) {
NSLog(@"第二个订阅者%@",x);
}];
//调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock
[subjest sendNext:@100];
[posable1 dispose];// 取消订阅 [subjest sendNext:@120];

RAC中的 集合类 RACTuple:元组类,类似NSArray,用来包装值

RACSequence:Rac中的集合类,用于代替NSArray,NSDictionary,可以使用它来快速遍历数组和字典 RACSequence使用场景:字典转模型

RACTuple简单使用: // 将数组转换层一个元组 RACTuple RACTuple tuple = [RACTuple tupleWithObjectsFromArray:@[@"1",@"2",@3,@4,@5]]; // 将元组转换为rac中的集合类RACSequence RACSequencesequence = tuple.rac_sequence; // 在将集合类(RACSequence)转换为信号(RACSignal) RACSignal *signal = sequence.signal; // 订阅信号,激活信号,会自动把集合中的所有值,遍历出来 [signal subscribeNext:^(id x) { NSLog(@"%@",x); }];

//可以链式调用
[tuple.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];

遍历字典: NSDictionary dict = @{@"name":@"程倩",@"age":@"26",@"sex":@"男"}; // 遍历字典 [dict.rac_sequence.signal subscribeNext:^(RACTuple x) {

    NSString *key = x[0];
NSString *value = x[1];
NSLog(@"%@ %@",key,value); }];

第二种遍历方式: NSDictionary dict = @{@"name":@"程倩",@"age":@"26",@"sex":@"男"}; // 遍历字典 [dict.rac_sequence.signal subscribeNext:^(RACTuple x) {

    // RACTupleUnpack  相当于 NSString *key = x[0];
// NSString *value = x[1];
RACTupleUnpack(NSString *key,NSString *value) = x;
NSLog(@"%@ %@",key,value); }];

字典转模型: NSString filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil]; NSArraydictArr = [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];
}]; // 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];

ReactiveCocoa开发中常见用法:

1.代替代理 rac_signalForSelector:用于替代代理 //rac_signalForSelector:将某个select转换为一个信号,然后订阅这个信号,系统调用这个函数的时候会发出信号 // 可以用来代替代理(但是不能传值)如果想传值使用RACSubject [[self rac_signalForSelector:@selector(didReceiveMemoryWarning)] subscribeNext:^(id x) { NSLog(@"系统调用了didReceiveMemoryWarning函数"); }];

  1. 代替KVO: rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变 // 代替KVO监听属性的改变这个函数需要导入NSObject+RACKVOWrapper.h头文件,这个文件默认没有导入 [self rac_observeKeyPath:@"name" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {

    NSLog(@"rac_observeKeyPath监听到值改变了");

    }]; //也可以将值改变转换为一个信号 然后订阅这个信号 [[self rac_valuesForKeyPath:@"name" observer:nil] subscribeNext:^(id x) { NSLog(@"rac_valuesForKeyPath监听到值改变了"); }]; 3.监听事件: rac_signalForControlEvents:用于监听某个事件 //监听按钮点击事件,返回一个信号,然后直接订阅这个信号 [[self.button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { NSLog(@"按钮被点击了"); }]; 4.代替通知 rac_addObserverForName:用于监听某个通知 // 代替通知中心 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"通知名称" object:nil] subscribeNext:^(id x) { NSLog(@"收到通知"); }]; [[NSNotificationCenter defaultCenter] postNotificationName:@"通知名称" object:nil];

  1. 监听文本框文字改变 rac_textSignal:只要文本框发出改变就会发出这个信号 // 监听文本框值的改变 [[self.textfield rac_textSignal] subscribeNext:^(id x) { NSLog(@"%@",x);//x是文本框中的值 }];

  2. 处理当界面有多次请求时,需要都获取到数据时,才能展示界面(两个信号都发送的 时候才会调用最后的select) // 6.处理多个请求,都返回结果的时候,统一做处理. RACSignal request1 = [RACSignal createSignal:^RACDisposable (id subscriber) { // 发送请求1 [subscriber sendNext:@"发送请求1"]; return nil; }];

    RACSignal request2 = [RACSignal createSignal:^RACDisposable (id subscriber) { // 发送请求2 [subscriber sendNext:@"发送请求2"]; return nil; }]; // 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。 [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];

ReactiveCocoa常见宏

1.RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定。 // 只要文本框中的文字改变就会修改lable中的文字 RAC(self.label,text) = self.textfield.rac_textSignal; 2.RACObserve(self, name):监听某个对象的某个属性,返回的是信号。 //RACObserve 监听某个对象的某个值,返回的是一个信号,其实就是ac_valuesForKeyPath函数 [RACObserve(self, name) subscribeNext:^(id x) {

    NSLog(@"%@",x);
}];
  1. @weakify(Obj)和@strongify(Obj),一般两个都是配套使用,解决循环引用问题. @weakify(self);// 将self转换成弱指针引用 RACSignal signal = [RACSignal createSignal:^RACDisposable (id subscriber) {

    @strongify(self) // 将self转换为强指针引用,只在当前block中有效
    
    NSLog(@"%@",self);
    
    return nil;

    }]; _signal = signal;

4.RACTuplePack:把数据包装成RACTuple(元组类) // 把参数中的数据包装成元组 RACTuple *tuple = RACTuplePack(@10,@20);

5.RACTupleUnpack:把RACTuple(元组类)解包成对应的数据。 // 把参数中的数据包装成元组 RACTupletuple = RACTuplePack(@"xmg",@20); // 解包元组,会把元组的值,按顺序给参数里面的变量赋值 // name = @"xmg" age = @20 RACTupleUnpack(NSString name,NSNumber *age) = tuple;

RACMulticastConnection:当一个信号被多次订阅的时候,为了保证创建信号时避免多次调用创建信号中的block造成副作用可以使用RACMulticastConnection RACMulticastConnection通过RACSignal的-publish或者-muticast:方法创建

简单使用: // RACMulticastConnection使用步骤: // 1.创建信号 + (RACSignal )createSignal:(RACDisposable (^)(id subscriber))didSubscribe // 2.创建连接 RACMulticastConnection *connect = [signal publish]; // 3.订阅信号,注意:订阅的不在是之前的信号,而是连接的信号。 [connect.signal subscribeNext:nextBlock] // 4.连接 [connect connect]

// RACMulticastConnection底层原理:
// 1.创建connect,connect.sourceSignal -> RACSignal(原始信号) connect.signal -> RACSubject
// 2.订阅connect.signal,会调用RACSubject的subscribeNext,创建订阅者,而且把订阅者保存起来,不会执行block。
// 3.[connect connect]内部会订阅RACSignal(原始信号),并且订阅者是RACSubject
// 3.1.订阅原始信号,就会调用原始信号中的didSubscribe
// 3.2 didSubscribe,拿到订阅者调用sendNext,其实是调用RACSubject的sendNext
// 4.RACSubject的sendNext,会遍历RACSubject所有订阅者发送信号。
// 4.1 因为刚刚第二步,都是在订阅RACSubject,因此会拿到第二步所有的订阅者,调用他们的nextBlock // 需求:假设在一个信号中发送请求,每次订阅一次都会发送请求,这样就会导致多次请求。
// 解决:使用RACMulticastConnection就能解决. // RACMulticastConnection:解决重复请求问题
// 1.创建信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"发送请求");
[subscriber sendNext:@1];
return nil;
}]; // 2.创建连接
RACMulticastConnection *connect = [signal publish]; // 3.订阅信号,
// 注意:订阅信号,也不能激活信号,只是保存订阅者到数组,必须通过连接,当调用连接,就会一次性调用所有订阅者的sendNext:
[connect.signal subscribeNext:^(id x) {
NSLog(@"订阅者一信号");
}];
[connect.signal subscribeNext:^(id x) {
NSLog(@"订阅者二信号");
}];
// 4.连接,激活信号
[connect connect];

RACCommand:Rac中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递包装到这个类中,可以很方便的监听事件的执行过程。

使用场景:监听按钮点击和网络请求。 // RACCommand:处理事件 // RACCommand:不能返回一个空的信号,会闪退 // 创建命令 RACCommand command = [[RACCommand alloc]initWithSignalBlock:^RACSignal (id input) { // 当前block执行命令的时候调用 // input 执行命令传入参数 NSLog(@"%@",input); return [RACSignal createSignal:^RACDisposable (id subscriber) { [subscriber sendNext:@"执行命令产生数据"]; return nil; }]; }]; // 如果要拿到执行命令产生的数据,执行命令返回一个信号,直接订阅信号 RACSignal signal = [command execute:@1]; // 订阅信号 [signal subscribeNext:^(id x) { NSLog(@"%@",x); }];

executionSignals:信号中的信号,发送的数据就是信号

//executionSignals:信号中的信号,发送的数据就是信号 // 订阅信号,必须要在执行命令之前订阅 [command.executionSignals subscribeNext:^(RACSignal *x) { [x subscribeNext:^(id x) { NSLog(@"%@",x); }]; }]; [command execute:@100];

switchToLatest:获取最新发送的信号,只能用于信号中信号

// switchToLatest获取最新发送的信号,只能用于信号中信号 // 获取到最新发送的信号直接订阅 [command.executionSignals.switchToLatest subscribeNext:^(id x) { NSLog(@"%@",x); }]; [command execute:@100];

监听任务是否执行完毕:

RACCommand command = [[RACCommand alloc]initWithSignalBlock:^RACSignal (id input) { NSLog(@"执行命令传入参数%@",input);

  return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

      [subscriber sendNext:@"执行命令产生数据"];
// 发送完成
[subscriber sendCompleted];
return nil;
}];

}];

// 监听任务是否执行完成
[command.executing subscribeNext:^(id x) {
if([x boolValue]==YES)
{
NSLog(@"当前任务正在执行");
}else{
NSLog(@"当前任务执行没有在执行");
}
}]; [command execute:@0];

ReactiveCocoa基础和一些常见类介绍的更多相关文章

  1. ReactiveCocoa常见操作方法介绍/MVVM架构思想

      1.ReactiveCocoa常见操作方法介绍. 1.1 ReactiveCocoa操作须知 所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中, ...

  2. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  3. ReactiveCocoa基础知识内容

    本文记录一些关于学习ReactiveCocoa基础知识内容,对于ReactiveCocoa相关的概念如果不了解可以网上搜索:RACSignal有很多方法可以来订阅不同的事件类型,ReactiveCoc ...

  4. ReactiveCocoa基础

    在讲ReactiveCocoa之前,我们来回忆一下Block在开发中的使用场景: 1.把block保存到对象中,等到恰当的时候才去调用 2.把block当做方法的参数使用,外界不调用,都是方法内部去调 ...

  5. Nmap扫描教程之网络基础服务DHCP服务类

    Nmap扫描教程之网络基础服务DHCP服务类 Nmap网络基础服务 网络基础服务是网络正常工作的基石,常见的网络基础服务包括DHCP服务和DNS服务.其中,DHCP服务用来为计算机动态分配IP地址:D ...

  6. CYQ.Data.Orm.DBFast 新增类介绍(含类的源码及新版本配置工具源码)

    前言: 以下功能在国庆期就完成并提前发布了,但到今天才有时间写文介绍,主要是国庆后还是选择就职了,悲催的是上班的地方全公司都能上网,唯独开发部竟不让上网,是个局域网. 也不是全不能上,房间里有三台能上 ...

  7. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  8. Object类介绍

    一.Object类介绍

  9. windows下mongodb基础玩法系列一介绍与安装

    windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) windows下 ...

随机推荐

  1. JSON与String之间互转

    一,String转json 这个JSON.parse()与eval()都可以实现,但是它们是有区别的, JSON.parse对json字符串要求比eval()更为严格,key名称(例如name)全部必 ...

  2. 转:js闭包

    一切都是对象 "一切都是对象"这句话的重点在于如何去理解"对象"这个概念. --当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascr ...

  3. 遇到的面试题-sql

    sql面试题(学生表_课程表_成绩表_教师表) 原帖链接:http://bbs.csdn.net/topics/280002741 表架构 Student(S#,Sname,Sage,Ssex) 学生 ...

  4. 英语学习APP案例分析

    第一部分 调研, 评测 1.上手体验 界面简洁,有常规的词典翻译功能,针对四六级或考研的人有特别的"单词挑战"模块,以及针对口语训练的"我爱说英语"模块,多功能 ...

  5. Java GUI+mysql+分页查询

    1.要求 : 创建一个学生信息管理数据库 2.实现分页查询 代码如下: a)学生实体类: /** * @author: Annie * @date:2016年6月23日 * @description: ...

  6. 【Alpha】——Second Scrum Meeting

    一.今日站立式会议照片 二.每个人的工作 成员 昨天已完成的工作 今天计划完成的工作 李永豪 完成登录按钮代码 完成添加功能 郑靖涛 完成登录按钮代码 完成删除功能 杨海亮 完成注册按钮代码 完成查找 ...

  7. 201521123035《Java程序设计》第十三周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...

  8. 201521123035《Java程序设计》第十周实验总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...

  9. 201521123048 《Java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  10. 201521123029《Java程序设计》第十三周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1.网络基础 1.1 比较ping www.baidu.com与ping cec.jmu. ...