ReactiveCocoa简单使用20例

1. 观察值变化
你别动,你一动我就知道。
//当self.value的值变化时调用Block,这是用KVO的机制,RAC封装了KVO
@weakify(self);
[RACObserve(self, value) subscribeNext:^(NSString* x) {
@strongify(self);
NSLog(@"你动了");
}];
2. 单边响应
你唱歌,我就跳舞。
//创建一个信号
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//这个信号里面有一个Next事件的玻璃球和一个Complete事件的玻璃球
[subscriber sendNext:@"唱歌"];
[subscriber sendCompleted];
return nil;
}];
//对信号进行改进,当信号里面流的是”唱歌”,就改成”跳舞”返还给self.value
RAC(self, value) = [signalA map:^id(NSString *value) {
if ([value isEqualToString:@"唱歌"]) {
return @"跳舞";
}
return @"";
}];
3. 双边响应
你向西,他就向东,他向左,你就向右。
//创建2个通道,一个从A流出的通道A和一个从B流出的通道B
RACChannelTerminal *channelA = RACChannelTo(self, valueA);
RACChannelTerminal *channelB = RACChannelTo(self, valueB);
//改造通道A,使通过通道A的值,如果等于"西",就改为"东"传出去
[[channelA map:^id(NSString *value) {
if ([value isEqualToString:@"西"]) {
return @"东";
}
return value;
}] subscribe:channelB];//通道A流向B
//改造通道B,使通过通道B的值,如果等于"左",就改为"右"传出去
[[channelB map:^id(NSString *value) {
if ([value isEqualToString:@"左"]) {
return @"右";
}
return value;
}] subscribe:channelA];//通道B流向A
//KVO监听valueA的值得改变,过滤valueA的值,返回YES表示通过
[[RACObserve(self, valueA) filter:^BOOL(id value) {
return value ? YES : NO;
}] subscribeNext:^(NSString* x) {
NSLog(@"你向%@", x);
}];
//KVO监听valueB的值得改变,过滤valueB的值,返回YES表示通过
[[RACObserve(self, valueB) filter:^BOOL(id value) {
return value ? YES : NO;
}] subscribeNext:^(NSString* x) {
NSLog(@"他向%@", x);
}];
//下面使valueA的值和valueB的值发生改变
self.valueA = @"西";
self.valueB = @"左";
帮助理解,我做了下面这个图,①②③④是打印顺序:

4. 代理
你是程序员,你帮我写个app吧。
//代理定义
@protocol ProgrammerDelegate
- (void)makeAnApp;
@end
/****************************************/
//为self添加一个信号,表示代理ProgrammerDelegate的makeAnApp方法信号
RACSignal *programmerSignal = [self rac_signalForSelector:@selector(makeAnApp)
fromProtocol:@protocol(ProgrammerDelegate)];
//设置代理方法makeAnApp的实现
[programmerSignal subscribeNext:^(RACTuple* x) {
//这里可以理解为makeAnApp的方法要的执行代码
NSLog(@"花了一个月,app写好了");
}];
//调用代理方法
[self makeAnApp];
5. 广播
知道你的频道,我就能听到你了。
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//注册广播通知
RACSignal *signal = [center rac_addObserverForName:@"代码之道频道" object:nil];
//设置接收到通知的回调处理
[signal subscribeNext:^(NSNotification* x) {
NSLog(@"技巧:%@", x.userInfo[@"技巧"]);
}];
//发送广播通知
[center postNotificationName:@"代码之道频道"
object:nil
userInfo:@{@"技巧":@"用心写"}];
6. 串联

两个管串联,一个管处理完自己的东西,下一个管才开始处理自己的东西

生活是一个故事接一个故事。
//创建一个信号管A
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//发送一个Next玻璃球和一个Complete玻璃球
[subscriber sendNext:@"我恋爱啦"];
[subscriber sendCompleted];
return nil;
}];
//创建一个信号管B
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//发送一个Next玻璃球和一个Complete玻璃球
[subscriber sendNext:@"我结婚啦"];
[subscriber sendCompleted];
return nil;
}];
//串联管A和管B
RACSignal *concatSignal = [signalA concat:signalB];
//串联后的接收端处理
[concatSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//打印:我恋爱啦 我结婚啦
7. 并联

两个管并联,只要有一个管有东西,就拿出来处理它。

污水都应该流入污水处理厂被处理。
//创建信号A
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"纸厂污水"];
return nil;
}];
//创建信号B
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"电镀厂污水"];
return nil;
}];
//并联2个信号
RACSignal *mergeSignal = [RACSignal merge:@[signalA, signalB]];
[mergeSignal subscribeNext:^(id x) {
NSLog(@"处理%@",x);
}];
8. 组合
//定义2个自定义信号
RACSubject *letters = [RACSubject subject];
RACSubject *numbers = [RACSubject subject];
//组合信号
[[RACSignal combineLatest:@[letters, numbers]
reduce:^(NSString *letter, NSString *number){
//把2个信号的信号值进行字符串拼接
return [letter stringByAppendingString:number];
}] subscribeNext:^(NSString * x) {
NSLog(@"%@", x);
}];
//自己控制发送信号值
[letters sendNext:@"A"];
[letters sendNext:@"B"];
[numbers sendNext:@"1"];//打印B1
[letters sendNext:@"C"];//打印C1
[numbers sendNext:@"2"];//打印C2

9. 合流压缩
我们是红白的
//创建信号A
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"红"];
[subscriber sendNext:@"白"];
return nil;
}];
//创建信号B
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"白"];
return nil;
}];
//合流后出来的是压缩包,需要解压才能取到里面的值
[[signalA zipWith:signalB] subscribeNext:^(RACTuple* x) {
//解压缩
RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
NSLog(@"我们是%@%@的", stringA, stringB);
}];
//打印:我们是红白的
10. 映射
我可以点石成金。
//创建信号,发送"石"玻璃球
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"石"];
return nil;
}];
//对信号进行改造,改造"石"为"金"
signal = [signal map:^id(NSString *value) {
if ([value isEqualToString:@"石"]) {
return @"金";
}
return value;
}];
//打印
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);//金
}];
11. 过滤
未满十八岁,禁止进入。
//创建信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@(15)];
[subscriber sendNext:@(17)];
[subscriber sendNext:@(21)];
[subscriber sendNext:@(14)];
[subscriber sendNext:@(30)];
return nil;
}]
//过滤信号,并打印
[[signal filter:^BOOL(NSNumber* value) {
//值大于等于18的才能通过过滤网
return value.integerValue >= 18;
}] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
//打印:21 30
12. 秩序(flattenMap方法也可以换成then方法,效果一样)
打蛋液,煎鸡蛋,上盘。
//创建一个信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"打蛋液");
[subscriber sendNext:@"蛋液"];
[subscriber sendCompleted];
return nil;
}]
//对信号进行秩序执行第一步
signal = [signal flattenMap:^RACStream *(NSString* value) {
//处理上一步的RACSignal的信号值value,这里value = @"蛋液"
NSLog(@"把%@倒进锅里面煎",value);
//返回下一步的RACSignal信号
return [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"煎蛋"];
[subscriber sendCompleted];
return nil;
}];
}];
//对信号进行秩序执行第二步
signal = [signal flattenMap:^RACStream *(NSString* value) {
//处理上一步的RACSignal的信号值value,这里value = @"煎蛋"
NSLog(@"把%@装到盘里", value);
//返回下一步的RACSignal信号
return [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"上菜"];
[subscriber sendCompleted];
return nil;
}];
}];
//最后打印
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
/*
打印:
打蛋液
把蛋液倒进锅里面煎
把煎蛋装到盘里
上菜
*/
13. 命令
我命令你马上投降。
//创建命令
RACCommand *aCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(NSString *input) {
//命令执行代码
NSLog(@"%@我投降了",input);
//返回一个RACSignal信号
return [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendCompleted];
return nil;
}];
}];
//执行命令
[aCommand execute:@"今天"];
//打印:今天我投降了
14. 延迟
等等我,我还有10秒钟就到了。
//创建一个信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"等等我,我还有10秒钟就到了");
[subscriber sendNext:@"车陂南"];
[subscriber sendCompleted];
return nil;
}];
//延时10秒接受Next玻璃球
[[RACSignal delay:10] subscribeNext:^(NSString *x) {
NSLog(@"我到了%@",x);
}];
/*
[2016-04-21 13:20:10]等等我,我还有10秒钟就到了
[2016-04-21 13:20:20]我到了车陂南
*/
15. 重放
一次制作,多次观看。
//创建一个普通信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"大导演拍了一部电影《我的男票是程序员》");
[subscriber sendNext:@"《我的男票是程序员》"];
return nil;
}];
//创建该普通信号的重复信号
RACSignal *replaySignal = [signal replay];
//重复接受信号
[replaySignal subscribeNext:^(NSString *x) {
NSLog(@"小明看了%@", x);
}];
[replaySignal subscribeNext:^(NSString *x) {
NSLog(@"小红也看了%@", x);
}];
/*
大导演拍了一部电影《我的男票是程序员》
小明看了《我的男票是程序员》
小红也看了《我的男票是程序员》
*/
16. 定时
每隔8个小时服一次药。
//创建定时器信号,定时8个小时
RACSignal *signal = [RACSignal interval:60*60*8
onScheduler:[RACScheduler mainThreadScheduler]];
//定时执行代码
[signal subscribeNext:^(id x) {
NSLog(@"吃药");
}];
17. 超时
等了你一个小时了,你还没来,我走了。
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//创建发送信息信号
NSLog(@"我快到了");
RACSignal *sendSignal = [RACSignal createSignal:^RACDisposable *(id sendSubscriber) {
[sendSubscriber sendNext:nil];
[sendSubscriber sendCompleted];
return nil;
}];
//发送信息要1个小时10分钟才到
[[sendSignal delay:60*70] subscribeNext:^(id x) {
//这里才发送Next玻璃球到signal
[subscriber sendNext:@"我到了"];
[subscriber sendCompleted];
}];
return nil;
}]
//这里对signal进行超时接受处理,如果1个小时都没收到玻璃球,超时错误
[[signal timeout:60*60
onScheduler:[RACScheduler mainThreadScheduler]]
subscribeError:^(NSError *error)
{
//超时错误处理
NSLog(@"等了你一个小时了,你还没来,我走了");
}];
18. 重试
成功之前可能需要数百次失败。
__block int failedCount = 0;
//创建信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
if (failedCount < 100) {
failedCount++;
NSLog(@"我失败了");
//发送错误,才会要重试
[subscriber sendError:nil];
} else {
NSLog(@"经历了数百次失败后");
[subscriber sendNext:nil];
}
return nil;
}];
//重试
RACSignal *retrySignal = [signal retry];
//直到发送了Next玻璃球
[retrySignal subscribeNext:^(id x) {
NSLog(@"终于成功了");
}];
19. 节流
不好意思,这里一秒钟只能通过一个人。
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//即时发送一个Next玻璃球
[subscriber sendNext:@"旅客A"];
//下面是GCD延时发送Next玻璃球
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(1 * NSEC_PER_SEC)),mainQueue, ^{
[subscriber sendNext:@"旅客B"];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2 * NSEC_PER_SEC)),mainQueue, ^{
//发送多个Next,如果节流了,接收最新发送的
[subscriber sendNext:@"旅客C"];
[subscriber sendNext:@"旅客D"];
[subscriber sendNext:@"旅客E"];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(3 * NSEC_PER_SEC)),mainQueue, ^{
[subscriber sendNext:@"旅客F"];
});
return nil;
}];
//对信号进行节流,限制短时间内一次只能接收一个Next玻璃球
[[signal throttle:1] subscribeNext:^(id x) {
NSLog(@"%@通过了",x);
}];
/*
[2015-08-16 22:08:45.677]旅客A
[2015-08-16 22:08:46.737]旅客B
[2015-08-16 22:08:47.822]旅客E
[2015-08-16 22:08:48.920]旅客F
*/
20. 条件(takeUntil方法:当给定的signal完成前一直取值)
直到世界的尽头才能把我们分开。
//创建取值信号
RACSignal *takeSignal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//创建一个定时器信号,每隔1秒触发一次
RACSignal *signal = [RACSignal interval:1
onScheduler:[RACScheduler mainThreadScheduler]];
//定时接收
[signal subscribeNext:^(id x) {
//在这里定时发送Next玻璃球
[subscriber sendNext:@"直到世界的尽头才能把我们分开"];
}];
return nil;
}];
//创建条件信号
RACSignal *conditionSignal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
//设置5秒后发生Complete玻璃球
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"世界的尽头到了");
[subscriber sendCompleted];
});
return nil;
}]
//设置条件,takeSignal信号在conditionSignal信号接收完成前,不断地取值
[[takeSignal takeUntil:conditionSignal] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
/*
[2015-08-16 22:17:22.648]直到世界的尽头才能把我们分开
[2015-08-16 22:17:23.648]直到世界的尽头才能把我们分开
[2015-08-16 22:17:24.645]直到世界的尽头才能把我们分开
[2015-08-16 22:17:25.648]直到世界的尽头才能把我们分开
[2015-08-16 22:17:26.644]直到世界的尽头才能把我们分开
[2015-08-16 22:17:26.645]世界的尽头到了
*/ http://www.cnblogs.com/ming1025/p/6072544.html

ReactiveCocoa简单使用20例的更多相关文章

  1. 裸设备和Oracle问答20例

    导读裸设备,也叫裸分区(原始分区),是一种没有经过格式化,不被Unix通过文件系统来读取的特殊字符设备.裸设备可以绑定一个分区,也可以绑定一个磁盘.本文收集裸设备和Oracle问答20例. 1.什么叫 ...

  2. [转]PROC简单使用用例--VC连接ORACLE

    [转]PROC简单使用用例--VC连接ORACLE 操作系统:windows 7 数据库版本:oracle 10g VS版本:VS2010 前言:连接ORACLE的方式有很多,此处仅以PROC为例,说 ...

  3. [hadoop系列]Pig的安装和简单演示样例

    inkfish原创,请勿商业性质转载,转载请注明来源(http://blog.csdn.net/inkfish ).(来源:http://blog.csdn.net/inkfish) Pig是Yaho ...

  4. PTA数据结构 习题2.1 简单计算器 (20分)

    习题2.1 简单计算器 (20分) 模拟简单运算器的工作.假设计算器只能进行加减乘除运算,运算数和结果都是整数,四种运算符的优先级相同,按从左到右的顺序计算. 输入格式: 输入在一行中给出一个四则运算 ...

  5. IDDD 实现领域驱动设计-一个简单业务用例的回顾和理解

    上一篇:<IDDD 实现领域驱动设计-由贫血导致的失忆症> 这篇博文是对<实现领域驱动设计>第一章后半部分内容的理解. Domain Experts-领域专家 这节点内容是昨天 ...

  6. Introspector(内省)简单演示样例 与 简单应用

    简单演示样例: package com.asdfLeftHand.test; import java.beans.BeanDescriptor; import java.beans.BeanInfo; ...

  7. JBoss 系列九十六:JBoss MSC - 简介及一个简单演示样例

    什么是 JBoss MSC JBoss MSC 即 JBoss Modular Service Container,是第三代 JBoss 产品 JBoss 7和WildFfly的内核,JBoss MS ...

  8. Thrift的安装和简单演示样例

    本文仅仅是简单的解说Thrift开源框架的安装和简单使用演示样例.对于具体的解说,后面在进行阐述. Thrift简述                                           ...

  9. GCD实现简单的单例类-Singletion

    什么是单例模式 1.单例模式是一个类在系统中只有一个实例对象.通过全局的一个入口点对这个实例对象进行访问.在 iOS 开发中,单例模式是非常有用的一种设计模式.如 下图,是一个简单单例模式的 UML ...

随机推荐

  1. Android This Activity already has an action bar supplied by the window decor

    This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_ ...

  2. netty底层是事件驱动的异步库 但是可以await或者sync(本质是future超时机制)同步返回 但是官方 Prefer addListener(GenericFutureListener) to await()

    io.netty.channel 摘自:https://netty.io/4.0/api/io/netty/channel/ChannelFuture.html Interface ChannelFu ...

  3. hpuoj--1287--HH实习(斐波那契数巧用)

    问题 D: HH实习 时间限制: 1 Sec  内存限制: 128 MB 提交: 53  解决: 37 [提交][状态][讨论版] 题目描述 这学期到了十五周了,HH突然要去实训中心实习了,想到要拿着 ...

  4. Mysql实战45讲 04讲深入浅出索引(上)读书笔记 极客时间

    极客时间 Mysql实战45讲 04讲深入浅出索引 极客时间(上)读书笔记  笔记体悟 1.索引的作用:提高数据查询效率2.常见索引模型:哈希表.有序数组.搜索树3.哈希表:键 - 值(key - v ...

  5. OKHttp使用简介

    现在android网络方面的第三方库很多,volley,Retrofit,OKHttp等,各有各自的特点,这边博客就来简单介绍下如何使用OKHttp. 梗概 OKHttp是一款高效的HTTP客户端,支 ...

  6. Parquet学习总结

    深入分析Parquet列式存储格式 Parquet是面向分析型业务的列式存储格式,由Twitter和Cloudera合作开发,2015年5月从Apache的孵化器里毕业成为Apache顶级项目,最新的 ...

  7. Nodemailer 报错

    { [Error: connect ECONNREFUSED] code: ‘ECONNREFUSED’, errno: ‘ECONNREFUSED’, syscall: ‘connect’ } 如果 ...

  8. P2742 [USACO5.1]圈奶牛Fencing the Cows

    题目描述 农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏.他建造的围栏必须包括他的奶牛喜欢吃草的所有地点.对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度. 输入输出格式 输入 ...

  9. Apache Ignite - 轉

    Ignite Docs Online: ignite-doc-cn https://dongwq.gitbooks.io/ignite-doc/content/index.html - Apache ...

  10. 设置IE浏览器文档模式版本

    浏览器版本问题是所有开发web的程序员共同的诟病,尤其是IE浏览器,笔者上次修改公司的一个项目中出现项目是在IE9没有出来之前,而现在修改时,则发现页面上出现的表格的错乱(因为表格是通过js动态生成的 ...