iOS-ReactiveCocoa學習筆記1

一篇關于RectiveCocoa的總結文檔

百度搜索了一下RectiveCocoa,都是與MVVM關聯在一起。

1·簡述下MVVM

MVC:ModelViewViewController

MVVM:ModelViewView-Model

Model:容納表現數據-模型對象信息的結構體,并在一個單獨的管理類中維護的創建/管理模型的統一邏輯。

View:包含實際 UI 本身(不論是 UIView 代碼, storyboard 和 xib), 任何視圖特定的邏輯, 和對用戶輸入的反饋. 在 iOS 中這不僅需要 UIView 代碼和那些文件, 還包括很多需由 UIViewController 處理的工作。

View-Model:

1、作為一個表現視圖顯示自身所需數據的靜態模型;

2、收集, 解釋和轉換那些數據;

收集:網絡請求,control控制的數值變更;

解釋:賦值;

轉換:viewmodel內的邏輯運算;

3、目的:讓view(controller)的任務更清晰,就是展示view-Model提供的數據。

Summary:Model不變,view不變,增加View-Model分擔ViewController的責任(每個view將有自己的view-model來約束)

其最終結果就是MVMCV

關于View-Model

不對視圖控制器起作用,或通告其變化

關于ViewController

1、不再發起網絡服務調用

2、不再管理數組(類似tableview的dataSource)

3、不再判斷某些值是否有效

4、其實就是不再管text或者image是什么了

5、只管view-Model中的變化

Summary:將view-model與view關聯,通過修改view model中的值的變更來修改view中的數值變化;ViewController就只能老老實實的管view-model的數值變更就好了。

2·ReactiveCocoa

解決View和View-Model關聯的問題

舉例

假設這是一個登陸頁面,我要判斷用戶名是否合法,密碼是否匹配,這些在MVC的情況下我都會在Controller中進行判斷,是的話會怎么怎么樣,不是的話會怎么怎么樣。

而在MVVM和RectiveCocoa的幫助下,我們可以使用一個登陸的ViewModel,所有的判斷和結果我可以寫在ViewModel中。而在Controller中我只要1、關聯用戶名的text和viewmodel中的username,密碼對應。2、就不用管TA了。

RectiveCocoa的學習

概念,一直是我不想去背卻又不得不背的東西。

1、RACSignal:RAC的構造單元,代表我們最終收到的信息,(當你能將未來某事某刻接收到的消息具體表示出來,我們可以預先運用邏輯構建信息流,而不是等到事件發生)

簡述:

1、信號是基本單位,也是寫完代碼會接收到的東西,因為是數據關聯在view和view-model上,我們可以提前將需要展示出來的數據在viewmodel中處理了,再通過關聯影響view的值的變化。而不是在controller中書寫了。(個人理解,如有偏差,請各種指正)

2、信號會為了控制通過應用的信息流而獲得所有這些異步方法(委托, 回調 block, 通知, KVO, target/action 事件觀察, 等)并將它們統一到一個接口下.這只是直觀理解. 不僅是這些, 因為信息會流過你的應用, 它還提供給你輕松轉換/分解/合并/過濾信息的能力.

簡述:中央集權制,信號中處理這些傳值方式;并通過書寫的邏輯達到預期的效果。

信號如何將ViewModel與View關聯上

信號是一個發送一連串值的物體。需要在訂閱者監聽時信號才會發信息,信號會向訂閱者發送0或多個帶有數值的’next’事件,后面帶有’complete’或’error’。

(信號類似于其他語言/工具包中的“promise”(1),但更強大,因為它不僅限于向它的訂閱者一次只傳遞一個返回值. )

1、創建一個信號

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {

return nil;

}];

2、信號中添加訂閱者接收到的東西

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {

//以下為新加

NSString *str=[NSString stringWithFormat:@"https://www.baidu.com"];

NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

NSURLRequest *request = [NSURLRequest requestWithURL:url];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]init];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

[subscriber sendNext:@""];

[subscriber sendCompleted];

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

[subscriber sendError:error];

}];

[operation start];

//end

return nil;

}];

3、RACObserve()

這個宏是 RAC 中對 KVO 中那些悲慘的 API 的替代。 你只需要傳入對象和你想觀察的那個對象某屬性的 keypath.。給出這些參數后, RACObserve 會創建一個信號,一旦它有了訂閱者,,它就立刻發送那個屬性的當前值,并在發送那個屬性在這之后的任何變化。

RACSignal *signal1 = RACObserve(self. personModel,name);

//這行代碼的前提是你有一個personModel,personModel有一個name屬性

這僅是提供用于創建信號的一個工具. 這里有幾個立即可用的方式, 來從內置控制流機制中拉取信號:

RACSignal *controlUpdate = [_myButtonrac_signalForControlEvents:UIControlEventTouchUpInside];

// signals for UIControl events send the control event value (UITextField, UIButton, UISlider, etc)

// subscribeNext:^(UIButton *button) { NSLog(@"%@", button); // UIButton instance }

RACSignal *textChange = [_myTextFieldrac_textSignal];

// some special methods are provided for commonly needed control event values off certain controls

// subscribeNext:^(UITextField *textfield) { NSLog(@"%@", _textfield.text); // "Hello!" }

RACSignal *alertButtonClicked = [_myAlertViewrac_buttonClickedSignal];

// signals for some delegate methods send the delegate params as the value

// e.g. UIAlertView, UIActionSheet, UIImagePickerControl, etc

// (limited to methods that return void)

// subscribeNext:^(NSNumber *buttonIndex) { NSLog(@"%@", buttonIndex); // "1" }

RACSignal *viewAppeared = [self rac_signalForSelector:@selector(viewDidAppear:)];

// signals for arbitrary selectors that return void, send the method params as the value

// works for built in or your own methods

// subscribeNext:^(NSNumber *animated) { NSLog(@"viewDidAppear %@", animated); // "viewDidAppear 1" }

什么是訂閱者?

簡言之,訂閱者就是一段代碼,它等待信號給它發送一些值,然后訂閱者就能處理這些值了. (它也可以作用于“complete”和“error”事件. )

簡述:理解為block,信號等同block調用?

RACSignal *usernameValidSignal = RACObserve(self. personModel,name);

// update the local property when this value changes

[usernameValidSignal subscribeNext: ^(NSNumber *isValidUserName) {

self.isValidName = isValidUserName.boolValue;

}];

以上代碼前提:controller 有一個personModel,有一個BOOL類型的isValidName,Model中有Number類型的isValidUserName

那問題來了,isValidName是BOOL為何我要傳NSNumber類型的。

答:RAC 只處理對象, 而不處理像 BOOL 這樣的原始值.。不過不用擔心,RAC 通常會幫你這些轉換。

RAC(self,isValidName) = RACObserve(self.personModel, isValidUserName);

//前面是target 后面是target下的@property

//用中文講,就是self.personModel的isValidUserName變化了,self.isValidName也要跟著變了。

那問題來了,self.isValidName做什么用,判斷嗎?那不就又繞回來了?把controller以前做判斷啊什么的邏輯交給viewmodel就好了,所以呢……

這樣我們可以把RACObserve(self.personModel, isValidUserName);綁定在textchange的協議方法中,或是確定按鈕的enable中,等等等等所有用這個值判斷的位置上(選位置時注意,不要總想在controller中操作)。

多個訂閱者, 副作用, 昂貴的操作

訂閱信號鏈時要明白重要的一件事是每當一個新值通過信號鏈被發送出去時, 實際上會給每個訂閱者都發送一次. 直到意識到這就我們而言是有意義的, 信號發出的值不存儲在任何地方(除了 RAC 在內部實現中). 當信號需要發送一個新的值時, 它會遍歷所有的訂閱者并給每個訂閱者發送那個值. (這是對信號鏈實際工作的簡化說明, 但基本想法是對的)

這為什么重要?這意味著信號鏈某處存在的任何副作用, 任何影響應用世界的轉變, 將會發生多次. 這對新接觸 RAC 的用戶來說是意想不到的. (這也違反了函數式構建的理念-數據輸入, 數據輸出).

一個做作的例子可能是: 信號鏈某處的信號在每次按鈕被按下時更新 self 中的一個計數器屬性. 如果信號鏈有多個訂閱者, 計數器的增長將會比你想的還要多. 你需要努力從信號鏈中盡可能剔除副作用. 當副作用不可避免時, 你可以使用一些恰當的預防機制. 我將會在另一篇文章中探索.

簡述:當存在多個訂閱者的時候,就像一對多廣播一樣,只要是訂閱者就會都遍歷一次。在設計之初就應該規范,不管是針對子viewModel的分別控制,還是條件限制,等等,

除副作用之外, 我們需要注意帶有昂貴操作和可變數據的信號鏈. 網絡請求就是一個三者兼得的例子:

網絡請求影響了應用的網絡層(副作用).

網絡請求為信號鏈引入了可變數據. (兩個完全一樣請求可能返回了不同的數據. )

網絡請求反應慢啊.

假設我根據一個text,text作為參數,發起多個網絡請求,我所要的結果在網絡請求的結果中,那么多個訂閱者如何處理這個返回結果,下一篇介紹RACCommand

額外:自行百度-mock、method swizzling

(1)promise的概念

ES6原生提供了Promise對象。

所謂Promise,就是一個對象,用來傳遞異步操作的消息。它代表了某個未來才會知道結果的事件(通常是一個異步操作),并且這個事件提供統一的API,可供進一步處理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容