[ReactiveCocoa](翻译|巨坑)FrameworkOverview框架概述

我厂广招各路大神加入:job.koudaitong.com
可以发简历到 tianchi@qima-inc.com O(∩_∩)O~

开坑前言

这个结结实实是一个巨坑,英语水平、技术水平有限,只是尝试着翻译一下,虽然ReactiveCocoa已经很流行,不过再segmentfault上还没看到他的踪影。

FrameworkOverview--框架概述

本文包含了ReactiveCocoa框架内的不同组成部分的一个高层次的描述,并试图解释它们如何协作以及划分责任。这是一个学信新的模块以及寻找更具体的文件的一个开始。

Streams

由RACStream抽象类来表示的Steam是任意对象的值的一个序列(any series of object values)。

值可以立即使用也可以在之后使用,但是必须按照顺序进行检索。不能在没有获取或者等待(without evaluating or waiting for the first value)第一个值的情况下获取第二个值。

Steams是单子(monads),除其他事项外,这使得复杂的操作必须建立在一些基本的原函数(primitives)上(特别是-bind:)。RACSteam也实现了HaskellMonoidMonadZip类型的等效(the equivalent of the Monoid and MonadZip typeclasses from Haskell)。

RACStream自身并不是十分有用。大多数stream被当作信号和序列来使用(treated as signals or sequences instead)。

Signals--信号

Signal有RACSignal类描述。它是一个push-driven的流。

信号一般表示将要传递的数据,随着工作(方法)的执行或者数据的接受,数据通过信号得到传递到订阅者(subscribers)处。用户必须订阅(subscribe)一个信号来访问它的值。

在三种不同类型的事件下信号会被发送给它的订阅者:
(Signals send three different types of events to their subscribers:)??
信号为它的订阅者发送三种不同类型的事件:

  • Steam中的下个(next)事件提供了新的值。RACSteam方法只会在这种类型的事件时执行。不想Cocoa中的collections,在信号中使用nil也是有效的。
  • 错误事件(error evenet)表示在信号结束前发生了一个错误。这个事件可能包含了一个NSError对象,指示什么地方除了错误。错误必须得到特殊的处理(handled specially),因为它们不包含在steam的值中。
  • 完成(complete)事件表示信号成功的结束了,并且没有更多的值被添加到steam中。完成后也必须进行特殊处理,原因相同。

一个信号的生命周期包括任何数量的next事件,以及一个error或者completed事件(两者不需要都有)。

Subscription--订阅

订阅者(subscriber)是正在等待或者能够等待来自信号的事件的任何对象。在RAC中,订阅者被表示为一个符合RACSubscriber协议的任何对象。

订阅可以通过调用-subscribeNext:error:completed:或者相应的适宜的方法来创建。从技术上讲,大部分RACStream和RACSignal方法能够很好的创建一个订阅,但是,这些中间订阅(intermediate subscriptions)通常是一个实现细节(implementation detail)。

订阅保留(retain)他们的信号,并在信号完成或者出错时被处理。订阅也可以被手动地处理。

Subjects

subject是一个可以手动控制的信号。它由RACSubject类进行描述。

subject可以看作是信号的一个“可变”变体(variant),就像NSMutableArray之于NSArray。它对于桥接(bridging)非RAC代码到信号中去(into the world of signals)非常有用。

举例来说,block可以简单的发送一个事件(event)给共享的subject来替代在block的回调中处理应用程序逻辑。之后subject可以返回一个RACSignal,隐藏回调的实现细节。

一些subject提供了额外的方法(behaviors)。尤其像RACReplaySubject能够被用来为之后的订阅者缓冲事件(buffer events),比如,一个网络请求在其他准备好处理请求结果之前完成。(when a network request finishes before anything is ready to handle the result)

Commands

command创建并订阅一个信号以响应一些动作(action)。这使得它很容易处理UI与应用之间的side-effecting work。

通常触发command的动作是由UI驱动的,比如按钮的点击。命令也可以根据信号被自动禁用,并且这种禁用状态能过通过禁用任何与command相关的控件来表现在UI上。

在OS X上,RAC为NSButton增加了一个rac_command属性来自动设置上述行为(behaviors)。

Connections

connection是一个在任意数量订阅者之间共享的一个订阅(subscription)。它由RACMulticastConnection类表示。

信号在默认情况下是“冷(code)”的,意思是,每当有一个新的订阅被添加了,信号就开始工作。这意味着每个订阅者的数据(data)会被重新计算。这种行为在一般情况下是可取的,但是如果信号具有side effects或者所要做的工作代价是昂贵的(比如发送一个网络请求)时,这就会有一些问题。

connection时通过RACSignal的-publish或者-muticast:方法创建的,并确保无论connection被订阅了多少次,只有一个相关的订阅被创建了。一旦连接了,连接的信号就被认为是“热(hot)”的,并且那个相关订阅会被保持活跃(remain active)直到所有connection上的订阅都被处理。

Sequences--序列

序列是个pull-driven的流,它由RACSequence类描述。

序列是一种集合,与NSArray类似。但是与数组不同的是,sequence中的值在默认情况下是延迟计算(evaluated lazily)的,如果只有一部分的sequence被使用,这会提高一定的性能。与Cocoa中的集合一样,序列中不允许包含nil

序列与Clojure中的序列(特别是lazy-seq)以及Haskell中的List类型相似。

RAC给大多数Cocoa的集合类添加了-rac_sequence方法,允许它们使用作为RACSequences。

Disposables

RACDisposables用于取消订阅与资源清理(cancellation and resource cleanup)。

Disposables最常用来退订(unsubscribe)一个信号。当一个订阅被处理之后,相应的订阅者将不会从信号中接受任何事件。另外,任何与订阅相关的的工作(后台进程、网络请求等等)会被取消,结果也不再需要。

Schedulers

Scheduler是信号执行工作以及返回它们的结果的一个串行执行队列。它由RACScheduler类描述。

Scheduler类似于GCD的队列(queue),但是scheduler支持取消操作,并且始终串行执行。唯一的例外是+immediateScheduler,schedulers不提供同步执行。这有助于避免死锁,并促使(encourages)用信号操作来替代block。

RACScheduler有时候也像NSOperationQueue,但是schedulers不允许任务重新排序与相互依赖。

Value types

为了方便表示流(steam)中的值,RAC提供了一些杂类(miscellaneous classes):

  • RACTuple是一个小型的、固定大小的集合,可以包括nil(由RACTupleNil表示)。它一般表示多个流的组合值(combined values)。
  • RACUnit是一个单例(singleton)的“空”值。它被用来表示那些在留中不存在的更有意义的数据。
  • RACEvent把任何信号事件(signal event)表示为信号值(signal value)。它主要通过RACSignal的-materialize来使用。

Asynchronous Backtraces

因为基于RAC的代码往往设计到异步的工作以及队列跳转(queue-hopping)。ReactiveCocoa框架支持支持捕获异步回溯,使得调试更加容易。

在OS X中,回溯会自动从任何代码捕捉,包括系统的库。

在iOS中,只有队列在RAC内跳转你的项目才会捕捉到(但是信息任然是有效的)。

后记

是在是有点坑,有些东西不是很清楚特别是用英语,不知道怎么翻译成中文。所以用括号标记出来,先做一个记录,在了解之后进行改进。

这只是个人的一个记录,翻译的不好不要喷我。附上一些学习RAC的网址:
http://blog.leezhong.com/ios/2013/06/19/frp-reactivecocoa.html
http://www.cnblogs.com/yangecnu/archive/2012/11/03/Introducting_ReactiveExtensions.html
http://www.cocoachina.com/applenews/devnews/2014/0115/7702.html
百度

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom