262

所以现在有了 swift,ReactiveCocoa的人已经在 3.0 版中为 swift 重写了它

此外,还有一个名为RxSwift的项目启动了。

我想知道人们是否可以添加有关这两个框架的设计/api/哲学差异的信息(请本着 SO 的精神,坚持真实的事情,而不是关于哪个“最好”的意见)

[StackOverflow 模组注意事项:这个问题确实有明确的答案,答案是两个框架之间的差异。我认为这对 SO 来说也很重要]

首先,我阅读他们的自述文件的最初印象是:

  • 作为熟悉微软“真正的”C# Rx 的人,RxSwift 看起来更容易识别。
  • ReactiveCococa 现在似乎已经进入了自己的领域,引入了新的抽象,例如 Signals vs SignalProducers 和 Lifting。一方面,这似乎澄清了某些情况(什么是热信号与冷信号),但另一方面,这似乎大大增加了框架的复杂性
4

1 回答 1

426

这个问题问得好。比较两个世界是非常困难的。Rx 是响应式扩展在其他语言(如 C#、Java 或 JS)中的一个端口。

Reactive Cocoa 受到了Functional Reactive Programming的启发,但在过去的几个月中,也有人指出它也受到了 Reactive Extensions的启发。结果是一个框架,它与 Rx 共享一些东西,但名称起源于 FRP。

首先要说的是,根据Conal对概念的定义,RAC 和 RxSwift 都不是函数响应式编程实现。从这一点开始,一切都可以简化为每个框架如何处理副作用和一些其他组件。

让我们谈谈社区和元技术的东西:

  • RAC 是一个已有 3 年历史的项目,诞生于 Objective-C,后来在完全放弃了 Objective-C 正在进行的工作后移植到 Swift(带有桥接器)的 3.0 版本。
  • RxSwift 是一个几个月前的项目,现在似乎在社区中有一股势头。对 RxSwift 很重要的一件事是它在ReactiveX组织之下,并且所有其他实现都以相同的方式工作,学习如何处理 RxSwift 将使使用 Rx.Net、RxJava 或 RxJS 成为一项简单的任务,只是一件小事的语言语法。我可以说这是基于一次学习,无处不在的哲学。

现在是时候使用技术了。

生产/观察实体

RAC 3.0 有 2 个主要实体,SignalSignalProducer一个实体发布事件,无论是否附加订阅者,第二个实体需要start实际产生信号/事件。创建这种设计是为了将冷热可观察对象的繁琐概念分开,这一直是许多开发人员困惑的根源。这就是为什么可以将差异减少到它们如何管理副作用的原因

在 RxSwift 中,Signal翻译SignalProducerObservable,这听起来可能令人困惑,但这两个实体在 Rx 世界中实际上是同一个东西。必须考虑到它们是热的还是冷的,在 RxSwift 中创建一个带有Observables 的设计,这听起来可能是不必要的复杂性,但是一旦你理解了它们是如何工作的(同样,热/冷/暖只是订阅/观察时的副作用) 他们可以被驯服。

在这两个世界中,订阅的概念基本相同,只是RAC引入的一点点不同,就是在发送完成事件之前处理interruptiona的事件。Signal回顾一下两者都有以下类型的事件:

  • Next, 计算新的接收值
  • Error,计算错误并完成流,取消订阅所有观察者
  • Complete, 将流标记为已完成取消订阅所有观察者

RAC 还具有在正确完成或错误完成之前处理interrupteda 时发送的内容。Signal

手动书写

在 RAC 中,Signal/SignalProducer是只读实体,它们不能从外部管理,Observable在 RxSwift 中也是如此。要将Signal/SignalProducer变成可写实体,您必须使用该pipe()函数返回手动控制的项目。在 Rx 空间中,这是一种不同的类型,称为Subject.

如果读/写概念听起来不熟悉,可以用Future/Promise做一个很好的类比。AFuture是只读占位符,例如Signal/SignalProducerObservable,另一方面, aPromise可以手动完成,例如 forpipe()Subject

调度器

这个实体在两个世界中非常相似,相同的概念,但是 RAC 是仅串行的,相反 RxSwift 还具有并发调度程序。

作品

组合是响应式编程的关键特征。组合流是这两个框架的本质,在 RxSwift 中它们也被称为序列

RxSwift 中的所有可观察实体都是 type 的ObservableType,所以我们用相同的操作符组合实例Subject和实例Observable,而不需要任何额外的关注。

在 RAC 空间中,Signal是2 个不同的SignalProducer实体,我们必须能够组合使用. 这两个实体有自己的操作符,所以当你需要混合事物时,你必须确保某个操作符可用,另一方面你忘记了热/冷的 observables。liftSignalProducerSignal

关于这部分,Colin Eberhardt总结得很好:

查看当前的 API,信号操作主要集中在“下一个”事件上,允许您在不同线程上转换值、跳过、延迟、组合和观察。而信号生产者 API 主要关注信号生命周期事件(完成、错误),操作包括 then、flatMap、takeUntil 和 catch。

额外的

RAC 还有 and 的概念ActionProperty前者是一种计算副作用的类型,主要与用户交互有关,后者在值发生变化时观察值执行任务时很有趣。在 RxSwift 中,它Action再次转换为Observable,这在 中很好地展示了RxCocoa,它是用于 iOS 和 Mac 的 Rx 原语的集成。RACProperty可以在 RxSwift中翻译成Variable(或)。BehaviourSubject

重要的是要理解Property/Variable是我们必须将命令式世界与反应式编程的声明性性质联系起来的方式,因此在处理第三方库或 iOS/Mac 空间的核心功能时,有时它是一个基本组件。

结论

RAC 和 RxSwift 是两个完全不同的野兽,前者在 Cocoa 领域有着悠久的历史和很多贡献者,后者相当年轻,但依赖于已被证明在其他语言(如 Java、JS 或。网。哪个更好的决定取决于偏好。RAC 指出热/冷 observable 的分离是必要的,这是框架的核心特性,RxSwift 说它们的统一比分离更好,这再次只是关于如何管理/执行副作用。

RAC 3.0 似乎在分离热/冷 observables 的主要目标之上引入了一些意想不到的复杂性,例如中断的概念、在 2 个实体之间拆分运算符以及引入一些命令式行为,例如start开始产生信号。对于某些人来说,拥有这些东西可能是一件好事,甚至是杀手级功能,而对于另一些人来说,它们可能只是不必要的,甚至是危险的。另一件要记住的事情是 RAC 试图尽可能地跟上 Cocoa 的约定,所以如果你是一个有经验的 Cocoa 开发者,你应该觉得使用它比使用 RxSwift 更舒服。

另一方面,RxSwift 有所有的缺点,比如热/冷 observables,但也有反应式扩展的优点。从 RxJS、RxJava 或 Rx.Net 迁移到 RxSwift 是一件简单的事情,所有的概念都是相同的,所以这使得寻找材料变得非常有趣,也许你现在面临的同样的问题,已经被 RxJava 中的某个人解决了,并且解决方案考虑到平台,可以重新应用。

选哪一个绝对是个人喜好问题,从客观的角度是无法判断哪一个更好的。唯一的方法是启动 Xcode 并尝试这两种方法,然后选择使用起来更舒服的一种。它们是相似概念的 2 个实现,试图实现相同的目标:简化软件开发。

于 2015-09-15T08:57:25.770 回答