响应式编程:ReactiveCocoa vs RxSwift


Today, my colleague explain to us about RxSwift. So I want to know that I should learning RxSwift or ReactiveCocoa. I found a good article on Stack Overflow. Now, I share with you.

Question

So now with swift, the ReactiveCocoa people have rewritten it in version 3.0 for swift

Also, there's been another project spun up called RxSwift.

I wonder if people could add information about what the differences in design/api/philosophy of the two frameworks are (please, in the spirit of SO, stick to things which are true, rather than opinions about which is "best")

[Note for StackOverflow mods: This question DOES have definitive answers, the answer is the differences between the two frameworks. I think it is also highly on topic for SO]

To get started, my initial impression from reading their ReadMe's is:

  • As someone who is familiar with the "real" C# Rx from microsoft, RxSwift looks a lot more recognisable.
  • ReactiveCococa seems to have gone off into it's own space now, introducing new abstractions such as Signals vs SignalProducers and Lifting. On the one hand this seems to clarify some situations (what's a Hot vs Cold signal) but on the other hand this seems to increase the complexity of the framework a LOT

Answer

This is a very good question. Comparing the two worlds is very hard. Rx is a port of what Reactive Extensions are in other languages like C#, Java or JS.

Reactive Cocoa was inspired by Functional Reactive Programming, but in the last months, has been also pointed as inspired by Reactive Extensions as well. The outcome is a framework that shares some things with Rx, but has names with origins in FRP.

The first thing to say is that neither RAC nor RxSwift are Functional Reactive Programming implementations, according to Conal's definition of the concept. From this point everything can be reduced to how each framework handles side effects and a few other components.

Let's talk about the community and meta-tech stuff:

  • RAC is a 3 years old project, born in Objective-C later ported to Swift (with bridges) for the 3.0 release, after completely dropping the ongoing work on Objective-C.
  • RxSwift is a few months old project and seems to have a momentum in the community right now. One thing that is important for RxSwift is that is under the ReactiveX organization and that all other implementations are working in the same way, learning how to deal with RxSwift will make working with Rx.Net, RxJava or RxJS a simple task and just a matter of language syntax. I could say that is based on the philosophy learn once, apply everywhere.
    Now it's time for the tech stuff.

Producing/Observing Entities

RAC 3.0 has 2 main entities, Signal and SignalProducer, the first one publishes events regardless a subscriber is attached or not, the second one requires a start to actually having signals/events produced. This design has been created to separate the tedious concept of hot and cold observables, that has been source of confusion for a lot of developers. This is why the differences can be reduced to how they manage side effects.

In RxSwift, Signal and SignalProducer translates to Observable, it could sound confusing, but these 2 entities are actually the same thing in the Rx world. A design with Observables in RxSwift has to be created considering if they are hot or cold, it could sound as unnecessary complexity, but once you understood how they work (and again hot/cold/warm is just about the side effects while subscribing/observing) they can be tamed.

In both worlds, the concept of subscription is basically the same, there's one little difference that RAC introduced and is the interruption event when a Signal is disposed before the completion event has been sent. To recap both have the following kind of events:

  • Next, to compute the new received value
  • Error, to compute an error and complete the stream, unsubscribing all the observers
  • Complete, to mark the stream as completed unsubscribing all observers

RAC in addition has interrupted that is sent when a Signal is disposed before completing either correctly or with an error.

Manually Writing

In RAC, Signal/SignalProducer are read-only entities, they can't be managed from outside, same thing is for Observable in RxSwift. To turn a Signal/SignalProducer into a write-able entity, you have to use the pipe() function to return a manually controlled item. On the Rx space, this is a different type called Subject.

If the read/write concept sounds unfamiliar, a nice analogy with Future/Promise can be made. A Future is a read-only placeholder, like Signal/SignalProducer and Observable, on the other hand, a Promise can be fulfilled manually, like for pipe() and Subject.

Schedulers

This entity is pretty much similar in both worlds, same concepts, but RAC is serial-only, instead RxSwift features also concurrent schedulers.

Composition

Composition is the key feature of Reactive Programming. Composing streams is the essence of both frameworks, in RxSwift they are also called sequences.

All the observable entities in RxSwift are of type ObservableType, so we compose instances of Subject and Observable with the same operators, without any extra concern.

On RAC space, Signal and SignalProducer are 2 different entities and we have to lift on SignalProducer to be able to compose what is produced with instances of Signal. The two entities have their own operators, so when you need to mix things, you have to make sure a certain operator is available, on the other side you forget about the hot/cold observables.

About this part, Colin Eberhardt summed it nicely:

Looking at the current API the signal operations are mainly focussed on the ‘next’ event, allowing you to transform values, skip, delay, combine and observe on different threads. Whereas the signal producer API is mostly concerned with the signal lifecycle events (completed, error), with operations including then, flatMap, takeUntil and catch.

Extra

RAC has also the concept of Action and Property, the former is a type to compute side effects, mainly relating to user interaction, the latter is interesting when observing a value to perform a task when the value has changed. In RxSwift the Action translates again into an Observable, this is nicely shown in RxCocoa, an integration of Rx primitives for both iOS and Mac. The RAC's Property can be translated into Variable (or BehaviourSubject) in RxSwift.

It's important to understand that Property/Variable is the way we have to bridge the imperative world to the declarative nature of Reactive Programming, so sometimes is a fundamental component when dealing with third party libraries or core functionalities of the iOS/Mac space.

Conclusion

RAC and RxSwift are 2 complete different beasts, the former has a long history in the Cocoa space and a lot of contributors, the latter is fairly young, but relies on concepts that have been proven to be effective in other languages like Java, JS or .NET. The decision on which is better is on preference. RAC states that the separation of hot/cold observable was necessary and that is the core feature of the framework, RxSwift says that the unification of them is better than the separation, again it's just about how side effects are managed/performed.

RAC 3.0 seems to have introduced some unexpected complexity on top of the major goal of separating hot/cold observables, like the concept of interruption, splitting operators between 2 entities and introducing some imperative behaviour like start to begin producing signals. For some people these things can be a nice thing to have or even a killer feature, for some others they can be just unnecessary or even dangerous. Another thing to remember is that RAC is trying to keep up with Cocoa conventions as much as possible, so if you are an experienced Cocoa Dev, you should feel more comfortable to work with it rather than RxSwift.

RxSwift on the other hand lives with all the downsides like hot/cold observables, but also the good things, of Reactive Extensions. Moving from RxJS, RxJava or Rx.Net to RxSwift is a simple thing, all the concepts are the same, so this makes finding material pretty interesting, maybe the same problem you are facing now, has been solved by someone in RxJava and the solution can be reapplied taking in consideration the platform.

Which one has to be picked is definitely a matter of preference, from an objective perspective is impossible to tell which one is better. The only way is to fire Xcode and try both of them and pick the one that feels more comfortable to work with. They are 2 implementations of similar concepts, trying to achieve the same goal: simplifying software development.

From:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容