你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> ReactiveCocoa 4 官方文檔翻譯

ReactiveCocoa 4 官方文檔翻譯

編輯:IOS開發基礎

譯者:@沒故事的卓同學

將翻譯幾篇ReactiveCocoa的文檔,這是第一篇。

QQ截圖20160224174241.png

ReactiveCocoa (RAC) 是一個Cocoa框架,受Functional Reactive Programming啟發。它提供API合成變換(composing and transforming)隨著時間改變的數據流。

兼容性

關於 RAC 4的文檔是在Swift 2.1.x下使用。對於Swift 1.2的支持請看 RAC 3.

介紹

ReactiveCocoa來源於functional reactive programming(Input and Output)。
區別於使用不斷變化修改的變量,RAC提供了“事件流”,通過 Signal 和SignalProducer 類型來表示, 它們隨著時間發送值。
事件流統一了Cocoa用於事件和異步處理的常用模式,包括:

  • 委托方法

  • 回調blocks

  • 通知

  • 控件的actions和響應事件鏈

  • Futures and promises

  • Key-value observing (KVO)

因為這些不同的機制能夠用一種相同的方式處理,可以很容易的聲明成鏈(chain)並且把它們聯合在一起,用更少的代碼和狀態連接它們。
更多關於RAC裡的概念可以查看Framework Overview.

例子:在線搜索

假設你有一個text field,每當用戶輸入文字時,你都會發起一個網絡請求根據輸入的關鍵字查詢。

實時觀察文字變化

實現這個目的的第一步,使用RAC中UITextField的一個擴展方法:

let searchStrings = textField.rac_textSignal() 
.toSignalProducer() 
.map { text in text as! String }

這樣產生了一個signal producer來發送輸入的字符串。( text as! String這種類型映射在當前是必需的,為了從OC橋接當前的擴展方法)

發送網絡請求

獲得了每次輸入的字符串,我們想要發送一個網絡請求。RAC也為我們提供了NSURLSession的一個擴展方法來實現:

 let searchResults = searchStrings
.flatMap(.Latest) { (query: String) -> SignalProducer in
  let URLRequest = self.searchRequestWithEscapedQuery(query)
  return NSURLSession.sharedSession().rac_dataWithRequest(URLRequest)}
.map { (data, URLResponse) -> String in
 let string = String(data: data, encoding: NSUTF8StringEncoding)!
 return self.parseJSONResultsFromString(string)}
.observeOn(UIScheduler())

這段代碼將字符串的producer轉換成了一組包含了搜索結果的producer,並且會在主線程中處理(由於UIScheduler的作用).。
另外這裡的flatMap(.Latest)確保只有最後的一次搜索會被執行。
如果當一個請求還在處理中,此時用戶輸入新的字符,在發起新的請求之前會取消之前的請求。想想這些如果自己實現的需要寫多少代碼!

接收結果

這樣實際上還沒有執行,因為producers必須started後才執行(對於返回結果沒有被使用時做的優化)。這個很簡單:

searchResults.startWithNext {
 results in print("Search results: (results)")
}

我們獲取值用於Next中的event:包含了請求結果,並且把他們log到了控制台。這裡也可以寫其他UI控制的代碼,比如reload一個table view。

失敗處理

到目前為止,這個例子中,任何的網絡錯誤都會產生一個Failed event,這會導致整個事件流終止。不幸的是,這意味著之後請求不會被發起。
為了避免這樣的情況,我們需要決定當失敗發生時怎樣處理。最快速的解決方案就是記錄它們,然後忽略它們:

.flatMap(.Latest) { (query: String) -> SignalProducer in 
 let URLRequest = self.searchRequestWithEscapedQuery(query)
 return NSURLSession.sharedSession() 
   .rac_dataWithRequest(URLRequest) 
   .flatMapError { error in 
   print("Network error occurred: (error)")
   return SignalProducer.empty
 } 
}

通過將失敗替換為空事件流,可以有效的忽略它們。
然而,在放棄前最好重試幾次。在一次,使用retry可以方便的達到這個目的。
改進後的searchResults producer會像這樣:

let searchResults = searchStrings 
  .flatMap(.Latest) { (query: String) -> SignalProducer in 
  let URLRequest = self.searchRequestWithEscapedQuery(query) 
  return NSURLSession.sharedSession() 
  .rac_dataWithRequest(URLRequest) 
  .retry(2) 
  .flatMapError { error in 
  print("Network error occurred: (error)") 
  return SignalProducer.empty } } 
  .map { (data, URLResponse) -> String in 
  let string = String(data: data, encoding: NSUTF8StringEncoding)! 
  return self.parseJSONResultsFromString(string) }
  .observeOn(UIScheduler())

降低請求頻率

現在,我們假設你只希望在用戶輸入暫停時才發起請求以減少網絡請求。
RAC通過throttle操作符可以用於實現這個需求:

let searchStrings = textField.rac_textSignal() 
  .toSignalProducer() 
  .map { text in text as! String } 
  .throttle(0.5, onScheduler: QueueScheduler.mainQueueScheduler)

這樣當間隔小於0.5秒時值不會被發送出去,意味著用戶必須停止編輯0.5秒後我們才會使用輸入的字符串去搜索。
如果用自己實現這個功能,真是要寫不少代碼,而且還會影響代碼的可讀性。但是在RAC中,只需要一個操作符就可以方便將時間控制加入事件流。

Objective-C 和 Swift

雖然RAC是作為一個OC的框架開始的,但是從版本3.0開始,所有的主要特性開發都是基於Swift API。
RAC的Objective-C API和Swift API是完全分開的,但是有一個bridge可以將他們互相轉換。這主要是為了兼容使用RAC的一些老項目,或者用於一些還沒有被加入Swfit API的一些Cocoa擴展。
Objective-C API將繼續存在,在可預計的未來將提供支持,但是不會有新的改進。關於使用這些API的信息可以參考:legacy documentation。
我們強烈建議所有的新項目采用Swift API。

ReactiveCocoa和Rx的關系

ReactiveCocoa 受了 Microsoft’s Reactive Extensions (Rx)庫的不少影響。有很多對於Rx的實現,包括RxSwift,但是ReactiveCocoa無意於成為Rx的一個實現子集。
RAC和 Rx的區別,主要有以下一些:

  • 更簡潔的API

  • 解決了令人困惑的常見問題

  • 更貼近Cocoa的編程習慣

命名

在大部分Rx的版本中,流被稱為Observables,對應於.NET中的Enumerable類型。
另外, Rx.NET大部分的操作符參考了LINQ,而LINQ是用於操作傳統關系型數據庫的,比如 Select和 Where。
RAC則最關注於匹配Swift的命名規范, 使用 map和 filter來替換select和where。其他的一些命名來源於Haskell或Elm(使用“signal”的始祖)。

Signals and Signal Producers (“hot” and “cold” observables)

Rx中的“hot”, “cold”, and “warm” observables (對應RAC中的事件流)很容易讓人困惑。

對於這個部分和Typed errors的區別,因為在我翻譯的iOS響應式編程:ReactiveCocoa vs RxSwift 選誰好中有更詳細的對比說明,這裡就不翻譯了。

Typed errors

處理錯誤時方式

UI編程

很多人不知道Rx怎麼用。即使用Rx進行UI的編程很常見,它有幾個特性用於一些特別的場景。
RAC從ReactiveUI借鑒了很多,包括Actions的基礎操作。
不像ReactiveUI不能直接將Rx改變的對於UI編程更友好,為了這個目的則進行了很多次的改動—即使這意味著和Rx的區別越來越大.

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved