如果你有看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
Reactive Programming
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
FRP傾向於技術理論上的方法論。MVVM則是程序模式的方法論。就好比FRP給了一把解牛的刀。MVVM就是如何解牛的方法論。
相對來說MVVM通常跟MVC拿來比較。在我看來,沒有絕對的好和壞。找個適合的就好了。再說我對兩個東西的瞭解不夠深入。
這篇blog應該就寫的蠻清楚了。
這是github上iOS的 MVVM例子MVVM-IOS-Example
大家可以感受一下。
ReactiveCocoa的基本使用方法
(終於寫到正主了,淚流滿面)
這裏借用Limboy的blog中的一段話作爲開場解釋。(因爲我想了好久都沒有想出超過他的比喻方法)
ReactiveCocoa是github去年開源的一個項目,是在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綁定在了一起。從而實現了我認爲我見過最簡單時鐘程序。表現了流和綁定響應。
組合
幾乎每個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借用的代碼和圖都是一樣的。
異步和網絡
(丟個鏈接 等心情好了 在補。。。)
總結
其實我對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
什麼是函數響應式編程(Functional Reactive Programming:FRP)
ReactiveCocoa
ReactiveCocoa與Functional Reactive Programming
Better Code for a Better World by Josh Abernathy
ReactiveCocoa: The Future of Cocoa Programming
Getting Started with ReactiveCocoa
Functional Reactive Programming on iOS with ReactiveCocoa
Basic MVVM with ReactiveCocoa
MVC - One Pattern to Rule them all
How I Wrote Vinylogue for iOS With ReactiveCocoa
ReactiveCocoa at MobiDevDay 2013