ReactiveCocoa框架菜鸟入门(五)——信号的FlattenMap与Map

2023-12-14 14:38

本文主要是介绍ReactiveCocoa框架菜鸟入门(五)——信号的FlattenMap与Map,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章背景

本文是在阅读《ReactiveCocoa入门教程:第一部分》一文后,提出的一些补充。主要是比较深入的研究了信号(Signal)的FlattenMap与Map与Map方法。

读者应该至少了解信号的概念,以及信号的基本操作。

问题提出

有时候,我们需要把一个异步的API用信号的方式来表示。比如,点击登录按钮后异步的访问服务器,当获取到数据的时候再调用订阅者的处理方法。一个可能会出现的代码大概是这样:、

- (RACSignal *)signInSignal {
return [RACSignal createSignal:^RACDisposable *(id subscriber){[self.signInService signInWithUsername:self.usernameTextField.textpassword:self.passwordTextField.textcomplete:^(BOOL success){[subscriber sendNext:@(success)];[subscriber sendCompleted];}];return nil;
}];
}[[[self.signInButtonrac_signalForControlEvents:UIControlEventTouchUpInside]map:^id(id x){return [self signInSignal];}]subscribeNext:^(id x){NSLog(@"Sign in result: %@", x);}];

这样的代码并不能正常运行,原文给出的解决方案是把map方法换成flattenMap方法,但是却没有给出解释。在此专栏的上一篇文章,我们已经研究过了flattenMap的工作原理,并且明确了一点:map方法是基于flattenMap方法实现的。

再探FlattenMap与Map

在了解这两个方法的工作原理之前,我们不妨梳理一下思路。对于一个信号流(由若干个信号前后拼接而成)中的每一个信号而言,我们最关心它能传递出什么数据,就像我们只关心水龙头里面流出的是水还是石油一样。至于流入的数据,一定是上一个信号的流出数据。

然而,在之前的讨论中我们已经清楚,信号能流出什么样的数据,是在创建这个信号的决定的。也就是说,订阅者拿到的数据,取决于在创建信号的时候,我们制定的sendNext方法的参数。与现实生活不同的是,我们可以在水龙头之间添加过滤网来实现类似的功能。

在《ReactiveCocoa框架菜鸟入门——信号(Signal)详解》一文中,我们已经详细的查看了bind方法和flattenMap方法的代码和文档。

flattenMap方法,实际上是根据前一个信号传递进来的参数重新建立了一个信号,这个参数,可能会在创建信号的时候用到,也有可能根本用不到。比如在之前的例子中,我们其实调用了自定义的方法来创建信号。

之前提到过,我们关注一个信号能传递什么数据出来,那么调用了flattenMap方法创建的信号,会传出什么样的值呢?

答案是不知道!!!

因为flattenMap方法并不关心生成的信号会传递什么值,它只负责根据前一个信号的参数创建一个新的信号!
而至于这个信号会传递什么值,之前也提到过,是在创建信号的时候指定的。比如本文所举的例子中,我们自定义的信号会传递这样的值

[subscriber sendNext:@(success)];

理解了这一点之后,map方法就简单了。先看一下map方法的定义:

- (instancetype)map:(id (^)(id value))block {NSCParameterAssert(block != nil);Class class = self.class;return [[self flattenMap:^(id value) {return [class return:block(value)];}] setNameWithFormat:@"[%@] -map:", self.name];
}

这里的[class return:block(value)]方法实现了flattenMap方法的功能,他返回了一个信号。return:方法的代码实现有点长,有兴趣的读者可以自行查阅,这里就不具体分析,总结来说就是,这个信号传递的值讲是block(value)。

flattenMap方法和map方法都有一个带参数value的block作为这个方法的参数。不同的是,flattenMap方法通过调用block(value)来创建一个新的方法。它可以灵活的定义新创建的信号。而map方法,将会创建一个和原来一模一样的信号,只不过新的信号传递的值变为了block(value)。

总结一下,个人对map的理解是“变换”。map方法,根据原信号创建了一个新的信号,并且变换了信号的输出值。这两个信号具有明显的先后顺序关系。而flattenMap方法,直接生成了一个新的信号,这两个信号并没有先后顺序关系,属于同层次的平行关系。这也许就是为什么会被命名为flattenMap吧。

实践检验

回头看一看此前的例子之所以用map方法不行的原因在于,map方法创建的信号,接收了前一个信号传递的值,传出的值是[self signInSignal]的执行结果,即任然是一个信号,但是我们并不需要这个信号,我们需要的是这个信号的传出值。

使用flattenMap方法就可行的原因在于,flattenMap方法生成了一个新的信号,也就是我们调用[self signInSignal]的执行结果。这个信号的传出的值,在信号的创建过程中已经被定义。所以可以正常工作。

吐槽一句

非常感谢最初翻译出ReactiveCocoa教程的大牛,给了我们快速入门的机会。但是能力越大,责任也越大,简单一句flattenMap可以处理信号中的信号,是非常不负责任的,可能会影响无数的学习者。甚至原作者当时也没能完全理解flattenMap的工作原理以及和map方法之间的关系。我想,严谨、求真知,是对任何一门科学的基本尊重。包括软件工程。

这句话,也送给未来的自己!

原网址 http://blog.csdn.net/abc649395594/article/details/46552865

这篇关于ReactiveCocoa框架菜鸟入门(五)——信号的FlattenMap与Map的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/492915

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否