ReactiveCocoa 4 文檔翻譯:基本操作符(二)

文檔地址:Basic Operators

本文將介紹:combineLatest、zip脆粥、flatten( .Merge, .Concat, .Latest)变隔、flatMapError蟹倾、retry、mapError肌厨、promoteErrors 操作符夏哭。

我翻譯的RAC4的文檔
ReactiveCocoa 4 官方文檔翻譯
ReactiveCocoa 4 文檔翻譯:基本操作符(一)
ReactiveCocoa 4 文檔翻譯:基本操作符(二)
ReactiveCocoa 4 文檔翻譯:框架組成介紹
ReactiveCocoa 4 文檔翻譯:兼容Objective-C
ReactiveCocoa 4 文檔翻譯--設(shè)計指南(一):事件的規(guī)范
ReactiveCocoa 4 文檔翻譯:設(shè)計指南(二):信號的規(guī)范
[翻譯]ReactiveCocoa 4 最佳實踐

組合事件流

下面的操作符將多個事件流的值組合成一個統(tǒng)一的新的事件流竖配。

按照最新的值組合

<code> combineLatest </code>函數(shù)可以把幾個事件流最新的值組合成一個新的事件流进胯。
合成后的新事件流只有在收到每個合成流的至少一個值后才會發(fā)送出去胁镐。接著就會把每個流的最新的值一起輸出诸衔。
<pre><code>
let (numbersSignal, numbersObserver) = Signal<Int, NoError>.pipe()

let (lettersSignal, lettersObserver) = Signal<String, NoError>.pipe()

let signal = combineLatest(numbersSignal, lettersSignal)

signal.observeNext { next in print("Next: (next)")}

signal.observeCompleted { print("Completed") }

numbersObserver.sendNext(0) // nothing printed

numbersObserver.sendNext(1) // nothing printed

lettersObserver.sendNext("A") // prints (1, A)

numbersObserver.sendNext(2) // prints (2, A)

numbersObserver.sendCompleted() // nothing printed

lettersObserver.sendNext("B") // prints (2, B)

lettersObserver.sendNext("C") // prints (2, C)

lettersObserver.sendCompleted() // prints "Completed"
</code></pre>
<code> combineLatestWith </code>操作符也是同樣的工作模式笨农。

combineLatest

可以看出在都收到兩個事件流的值竭宰,1和A后份招,開始輸出(1,A)廓旬。接著每有一個值輸入孕豹,就根據(jù)兩個流最近輸入的值輸出值怔蚌。

Zipping(拉鏈)

<code> zip </code>將兩個(或者多個)事件流的值成對組合桦踊。就像拉鏈一樣籍胯。將每個事件流的值按照索引順序組合輸出杖狼。意味著如果是一個流的第N個元素,一定要等到另外一個流第N值也收到才會一起組合發(fā)出理朋。
<pre><code>
let (numbersSignal, numbersObserver) = Signal<Int, NoError>.pipe()

let (lettersSignal, lettersObserver) = Signal<String, NoError>.pipe()

let signal = zip(numbersSignal, lettersSignal)

signal.observeNext { next in print("Next: (next)") }

signal.observeCompleted { print("Completed") }

numbersObserver.sendNext(0) // nothing printed

numbersObserver.sendNext(1) // nothing printed

lettersObserver.sendNext("A") // prints (0, A)numbersObserver.sendNext(2) // nothing printed

numbersObserver.sendCompleted() // nothing printed

lettersObserver.sendNext("B") // prints (1, B)

lettersObserver.sendNext("C") // prints (2, C) & "Completed"
</code></pre><code> zipWith </code>操作符也是同樣的工作模式嗽上。
圖示中,前面4個值都會組合輸出彼念。注意第一個流的5逐沙,因為第二個事件流沒有第5個值還沒有收到洼畅,所以沒有發(fā)出。


zip

壓平信號產(chǎn)生源(Flattening producers)

<code> flatten </code> 將一個事件流里的事件流變成一個單一的事件流务热。新的事件流的值按照指定的策略(FlattenStrategy)由內(nèi)部的事件流的值組成崎岂。
被壓平的值按照會變成外層的流的類型冲甘。比如:一個SignalProducers里的Signal江醇,被flatten后的類型是SignalProducers何暇。
想象下面values里面的三組值的發(fā)出時間根據(jù)圖里的位置排列裆站。



簡單的說就是merge按照時間順序組成羽嫡,concat則是按照里面整個流順序組合肩袍。latest是只記錄最近一次過來的值的那個流氛赐。

合并

<code> .Merge </code> 策略將每個流的值立刻組合輸出。無論內(nèi)部還是外層的流如果收到失敗就終止甫窟。
<pre><code>
let (producerA, lettersObserver) = SignalProducer<String, NoError>.buffer(5)

let (producerB, numbersObserver) = SignalProducer<String, NoError>.buffer(5)

let (signal, observer) = SignalProducer<SignalProducer<String, NoError>, NoError>.buffer(5)

signal.flatten(.Merge).startWithNext { next in print(next) }

observer.sendNext(producerA)

observer.sendNext(producerB)

observer.sendCompleted()

lettersObserver.sendNext("a") // prints "a"

numbersObserver.sendNext("1") // prints "1"

lettersObserver.sendNext("b") // prints "b"

numbersObserver.sendNext("2") // prints "2"

lettersObserver.sendNext("c") // prints "c"

numbersObserver.sendNext("3") // prints "3"
</code></pre>
示意圖:


連接

<code> .Concat </code> 策略是將內(nèi)部的SignalProducer排序。外層的producer是馬上被started街图。隨后的producer直到前一個發(fā)送完成后才會start餐济。一有失敗立即傳到外層絮姆。
<pre><code>
let (producerA, lettersObserver) = SignalProducer<String, NoError>.buffer(5)

let (producerB, numbersObserver) = SignalProducer<String, NoError>.buffer(5)

let (signal, observer) = SignalProducer<SignalProducer<String, NoError>, NoError>.buffer(5)

signal.flatten(.Concat).startWithNext { next in print(next) }

observer.sendNext(producerA)

observer.sendNext(producerB)

observer.sendCompleted()

numbersObserver.sendNext("1") // nothing printed

lettersObserver.sendNext("a") // prints "a"

lettersObserver.sendNext("b") // prints "b"

numbersObserver.sendNext("2") // nothing printed

lettersObserver.sendNext("c") // prints "c"

lettersObserver.sendCompleted() // prints "1", "2"

numbersObserver.sendNext("3") // prints "3"

numbersObserver.sendCompleted()
</code></pre>


轉(zhuǎn)向最新的流

<code> .Latest </code>只接收最新進(jìn)來的那個流的值蚁阳。
<pre><code>
let (producerA, observerA) = SignalProducer<String, NoError>.buffer(5)

let (producerB, observerB) = SignalProducer<String, NoError>.buffer(5)

let (producerC, observerC) = SignalProducer<String, NoError>.buffer(5)

let (signal, observer) = SignalProducer<SignalProducer<String, NoError>, NoError>.buffer(5)

signal.flatten(.Latest).startWithNext { next in print(next) }

observer.sendNext(producerA) // nothing printed

observerC.sendNext("X") // nothing printed

observerA.sendNext("a") // prints "a"observerB.sendNext("1") // nothing printed

observer.sendNext(producerB) // prints "1"

observerA.sendNext("b") // nothing printed

observerB.sendNext("2") // prints "2"

observerC.sendNext("Y") // nothing printed

observerA.sendNext("c") // nothing printed

observer.sendNext(producerC) // prints "X", "Y"

observerB.sendNext("3") // nothing printed

observerC.sendNext("Z") // prints "Z"
</code></pre>

處理失敗

下面這些操作符用戶處理事件流產(chǎn)生的失敗螺捐。

捕捉失敗

<code> flatMapError </code>捕捉一個由SignalProducer產(chǎn)生的失敗定血,然后產(chǎn)生一個新的SignalProducer代替诞外。
<pre><code>
let (producer, observer) = SignalProducer<String, NSError>.buffer(5)

let error = NSError(domain: "domain", code: 0, userInfo: nil)

producer

.flatMapError { _ in SignalProducer<String, NoError>(value: "Default") }

.startWithNext { next in print(next) }

observer.sendNext("First") // prints "First"

observer.sendNext("Second") // prints "Second"

observer.sendFailed(error) // prints "Default"
</code></pre>

重試

<code> retry </code>用于按照指定次數(shù)茫虽,在失敗時重啟SignalProducer靖苇。
<pre><code>
var tries = 0

let limit = 2

let error = NSError(domain: "domain", code: 0, userInfo: nil)

let producer = SignalProducer<String, NSError> { (observer, _) in

if tries++ < limit {

observer.sendFailed(error)

} else {

observer.sendNext("Success")

observer.sendCompleted()

}

}

producer

.on(failed: {e in print("Failure")}) // 打印 "Failure" 兩次

.retry(2)

.start { event in

switch event { case let .Next(next): print(next) // 打印 "Success"

case let .Failed(error):

print("Failed: (error)")

case .Completed:

print("Completed")

case .Interrupted:

print("Interrupted")
}

}
</code></pre>
如果按照指定次數(shù)還沒有成功贤壁,就會輸出失敗脾拆。

映射錯誤 (Mapping errors)

<code> mapError </code>會將事件流里的任何一個失敗映射成一個新的錯誤。


產(chǎn)生(Promote)

<code> promoteErrors </code> 可以在一個正常的流里產(chǎn)生一個錯誤旨怠,類似throw鉴腻。
<pre><code>
let (numbersSignal, numbersObserver) = Signal<Int, NoError>.pipe()

let (lettersSignal, lettersObserver) = Signal<String, NSError>.pipe()

numbersSignal

.promoteErrors(NSError)

.combineLatestWith(lettersSignal)
</code></pre>
歡迎關(guān)注我的微博:@沒故事的卓同學(xué)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市器一,隨后出現(xiàn)的幾起案子课锌,更是在濱河造成了極大的恐慌,老刑警劉巖祈秕,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渺贤,死亡現(xiàn)場離奇詭異,居然都是意外死亡请毛,警方通過查閱死者的電腦和手機(jī)志鞍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來获印,“玉大人述雾,你說我怎么就攤上這事〖娣幔” “怎么了玻孟?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵艳丛,是天一觀的道長碰酝。 經(jīng)常有香客問我,道長墨吓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮历极,結(jié)果婚禮上氏义,老公的妹妹穿的比我還像新娘。我一直安慰自己克婶,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布晒哄。 她就那樣靜靜地躺著,像睡著了一般红符。 火紅的嫁衣襯著肌膚如雪刹前。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天耍目,我揣著相機(jī)與錄音莫辨,去河邊找鬼。 笑死蟆融,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了州弟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后黎炉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體趁仙,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡痊焊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年刁愿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖已艰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布绽昏,位于F島的核電站认然,受9級特大地震影響腾务,放射性物質(zhì)發(fā)生泄漏担钮。R本人自食惡果不足惜宰啦,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一叨吮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春颜说,著一層夾襖步出監(jiān)牢的瞬間玄妈,已是汗流浹背酝锅。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像欢瞪,于是被迫代替她去往敵國和親骑祟。 傳聞我的和親對象是個殘疾皇子健民,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容