ReactiveCocoa

如果你有看Github的Trending Objective-C榜單,那你肯定是見過ReactiveCocoa了。如果你在weibo上關注唐巧、onevcat等國內一線知名開發者。那也應該聽說過ReactiveCocoa了。

ReactiveCocoa更加被Mattt Thompson大神稱爲開啓一個新Objective-C紀元。

當然也有人聲稱ReactiveCocoa是Cocoa的未來。ReactiveCocoa: The Future of Cocoa Programming

我自己粗獷把現在的Objective-C分爲兩個階段。

第一個階段就是我學Cocoa開發之前的階段:就是把Objective-C做出來的那羣NeXT的大神,確定面向對象思想,確定消息機制,確定各種模式最後變成了Apple的主力開發語言。到後面OS X的各種庫。iOS的各種庫。

第二個階段就是我學Cocoa開發之後的階段:開始clang發力,配合Objective-C的快速進化:ARC,block,現代Objective-C語法。使其Objective-C不斷獲得現代語言類如Ruby, Python的優秀特性。

現在,說的最多的就是ReactiveCocoa將會把Objective-C帶到下一個里程碑中。

ReactiveCocoa是一個基於Functional Reactive Programming編程思想的Objective-C實現開源的第三方庫。最初的作者是Github的大神(Josh Abernathy & Justin Spahr-Summers)。應該是再開發Github For Mac時候的附屬產物。當然,我們必需得明白有時候附屬產物要比真主牛逼的多了去了。比如萬艾可,再比如青黴素,再再比如老乾媽。

等等 什麼是Functional Reactive Programming

Functional Reactive Programming

wiki解釋

Reactive Programming

wiki 響應式編程

Functional programming

wiki Functional programming

恩 簡單來說

Functional Reactive Programming = Functional programming + Reactive Programming

(PS:特麼太偷懶了還是解釋一下)

簡單以

a = b + c

爲例

通常情況下在執行a = b + c的值的時候b和c當時是什麼值。a就是當時的b+c。然後後來不管b和c怎麼變化,a都不會改變。

但是在Execl中設置a格子=b格子+c格子的值。a的值就會隨着b和c值的改變而改變。然後我還可以搞的高級一點f = a + d。 f格子的值也會隨着b、c、d的值而改變。這就是使用Functional Reactive Programming以後會發生的情況。

Reactive的特性使得可以隨時響應變化。Functional的特性使得他們可以串起來。

來自微軟實驗室的編程思想

ReactiveCocoa的readme我們看到ReactiveCocoa是基於.NET的Reactive Extensions(Rx)來的。嘖嘖身爲一個腦殘果粉不解釋的我。也必須承認微軟其實曾經一度集聚這世界上一大批大牛。這批大牛在閒着玩的時候做出來的玩具也指不定哪天就拯救世界了。

Rx

所以我也找了點Rx的資料來看看

中文裏面比較全面的是這個
Reactive Extensions入門

裏面有一堆鏈接和一個視頻。c#實在看不懂,就只看了15分鐘左右。不過那看上去蠻帥的哥們一開始說他在編程中遇到的問題。恰巧是我最近遇到的問題:就是我有兩個在非主線程的異步操作。而我有可能需要等兩個異步操作都完成的時候進行下一步操作。這種情況我一直沒有找到比較優美的解決方法。直到遇見ReactiveCocoa,彷彿看見了希望。

Model-View-ViewModel

洋文wiki

中文wiki

FRP傾向於技術理論上的方法論。MVVM則是程序模式的方法論。就好比FRP給了一把解牛的刀。MVVM就是如何解牛的方法論。

相對來說MVVM通常跟MVC拿來比較。在我看來,沒有絕對的好和壞。找個適合的就好了。再說我對兩個東西的瞭解不夠深入。

Basic MVVM with ReactiveCocoa

這篇blog應該就寫的蠻清楚了。

這是github上iOS的 MVVM例子MVVM-IOS-Example

大家可以感受一下。

ReactiveCocoa的基本使用方法

(終於寫到正主了,淚流滿面)

這裏借用Limboy的blog中的一段話作爲開場解釋。(因爲我想了好久都沒有想出超過他的比喻方法)

ReactiveCocoagithub去年開源的一個項目,是在iOS平臺上對FRP的實現。FRP的核心是信號,信號在ReactiveCocoa(以下簡稱RAC)中是通過RACSignal來表示的,信號是數據流,可以被綁定和傳遞。
可以把信號想象成水龍頭,只不過裏面不是水,而是玻璃球(value),直徑跟水管的內徑一樣,這樣就能保證玻璃球是依次排列,不會出現並排的情況(數據都是線性處理的,不會出現併發情況)。水龍頭的開關默認是關的,除非有了接收方(subscriber),纔會打開。這樣只要有新的玻璃球進來,就會自動傳送給接收方。可以在水龍頭上加一個過濾嘴(filter),不符合的不讓通過,也可以加一個改動裝置,把球改變成符合自己的需求(map)。也可以把多個水龍頭合併成一個新的水龍頭(combineLatest:reduce:),這樣只要其中的一個水龍頭有玻璃球出來,這個新合併的水龍頭就會得到這個球。

替代KVO

官方例子:官方的例子貌似用了比較老的函數。 我改完以後看見什麼是函數響應式編程(Functional Reactive Programming:FRP)他也是這麼改的。說明一下。

1
2
3
4
5
6
@property (strong) NSString *username;


[RACAble(self, username) subscribeNext:^(NSString *newName) {
    NSLog(@"%@", newName);
}];

在這句代碼以後,只要你的username有變化。都可以打印出來。實現了KVO的功能卻減少了無數的代碼。體現了綁定和響應。

高級一個點的官方例子

1
2
3
4
5
6
7
[[RACAble(self, username)
  filter:^(NSString *newName) {
      return [newName hasPrefix:@"j"];
  }]
 subscribeNext:^(NSString *newName) {
     NSLog(@"%@", newName);
 }];

第一個例子是簡單的所有變化都會響應到。但是可能我只想響應部分情況。這時候就用filter來過濾。filter的block返回YES的情況就是需要觸發的情況。其他就補返回。所以這代碼以後。 username以j開頭的才能打印出來。

流的實現

以下是Getting Started with ReactiveCocoa的例子和圖片

如何以最少的代碼實現一個時鐘應用

1
2
3
4
5
RAC(self.textField.text) = [[[RACSignal interval:1] startWith:[NSDate date]] map:^id(NSDate *value) {
    NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:value];
    
    return [NSString stringWithFormat:@"02%ld:%02ld:%02ld",(long)dateComponents.hour, dateComponents.minute, (long)dateComponents.second];
}];

實現的邏輯順序是這樣的。設置一個間隔爲一秒。從現在開始調用的函數。並把當前實際傳入。 這個函數返回一個NSString。 然後把這個NSString和界面上的textField綁定在了一起。從而實現了我認爲我見過最簡單時鐘程序。表現了流和綁定響應。

原blog中對上述代碼的流的形容圖原blog中對上述代碼的流的形容圖

組合

幾乎每個ReactiveCocoa的Demo裏面都會出現的例子。

(繼續盜圖圖)

這個是用的leezhong的圖。 應該是從這個演講PPT裏面來的,點過去還有視頻哦

就是說在必需驗證每個所填寫的數值符合標準。Button才能點擊。

1
2
3
RAC(self.submitButton.enabled) = [RACSignal combineLatest:@[self.usernameField.rac_textSignal, self.passwordField.rac_textSignal] reduce:^id(NSString *userName, NSString *password) {
    return @(userName.length >= 6 && password.length >= 6);
}];

簡單的解釋就是把usernameField和passwordField的信號綁定在了一起做reduce處理以後。返回一個BOOL值去跟self.submitButton.enabled進行綁定。

囧。再次發現和leezhong借用的代碼和圖都是一樣的。

異步和網絡

(丟個鏈接 等心情好了 在補。。。)

when-to-use-reactivecocoa

總結

其實我對ReactiveCocoa瞭解還是在hello world階段。 很多東西都理解的很粗糙。上面這一大陀blog。很多地方寫的肯定不好。歡迎指出。其實很多時候覺得確實中文原創的技術文章十分少。很大一部分都是翻譯的。國外的技術文章也確實寫的牛寫的好。但是總覺得自己應該寫點自己思考的東西。

對於ReactiveCocoa來說,我認爲它確實是一個好東西。正如leezhong所說
RAC統一了對KVO、UI Event、Network request、Async work的處理,因爲它們本質上都是值的變化(Values over time)。

其實App上90%的操作不就只有這些麼。所以我會一直對ReactiveCocoa投入時間去學習和使用。順便說一句。阿里Mac Lab出品的Xiami for Mac。是我見過國內最好的Mac App之一。他們也用了ReactiveCocoa。然後你可以想象對他們做出那些響應交互ReactiveCocoa爲他們提供了強有力的輸出。

參考資料

FRP

wiki Functional reactive programming

趣味編程:Functional Reactive Programming

haskell Functional Reactive Programming

wiki 響應式編程

wiki Functional programming

函數式反應型編程(FRP) —— 實時互動應用開發的新思路

什麼是函數響應式編程(Functional Reactive Programming:FRP)

Reactive Extensions入門

ReactiveCocoa

ReactiveCocoa與Functional Reactive Programming

Better Code for a Better World by Josh Abernathy

nshipster Reactive​Cocoa

ReactiveCocoa: The Future of Cocoa Programming

Getting Started with ReactiveCocoa

Functional Reactive Programming on iOS with ReactiveCocoa

Basic Operators

Basic MVVM with ReactiveCocoa
MVC - One Pattern to Rule them all

How I Wrote Vinylogue for iOS With ReactiveCocoa

來自好友RoCry的推薦

ReactiveCocoa at MobiDevDay 2013

ReactiveCocoa at MobiDevDay 2013視頻

Input and Output

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章