我厂广招各路大神加入: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也实现了Haskell中Monoid与MonadZip类型的等效(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
百度