官方文檔:
http://reactivecocoa.io/reactiveswift/docs/latest/index.html
實戰(zhàn)項目:
https://github.com/JornWu/ZhiBo_Swift.git
一、什么是ReactiveSwift
ReactiveSwift
提供了可組合的、聲明性和靈活的圍繞“隨時間推移的值流”這種宏觀概念而創(chuàng)建的實體顺呕。
這些實體從根本上是一種監(jiān)視行為掠兄,可用于統(tǒng)一地代表通常Cocoa上和通用的編程模式碉渡。如:代理
焰扳、回調(diào)閉包
丈甸、通知
渔伯、控制行為
顶霞、事件響應(yīng)者鏈
、未來/承諾
和KVO
锣吼。
因為這些不同的機制可以用相同方式來都表示选浑。可以把要處理的事情玄叠,和監(jiān)聽的事情的代碼放在一起古徒,這樣非常方便我們管理,就不需要跳到對應(yīng)的方法里读恃。非常符合我們開發(fā)中高聚合隧膘,低耦合的思想。
二寺惫、核心Reactive實體
1疹吃、Signal:單向事件流
Signal
的所有者對事件流持有單方面的控制。觀察者可以在任何時候注冊接收他們所感興趣的事件西雀。但是這些觀察對事件流或者其所有者都沒side effect
萨驶。
let channel: Signal<Program, NoError> = tvStation.channelOne
channel.observeValues { program in ... }
2、Event:事件流的基本傳輸單位
一個Signal
可以擁有任意數(shù)量的攜帶著值的Event
艇肴,這些事件最后跟隨著一個特別原因的終止事件腔呜。
3、SignalProducer:創(chuàng)建值流的延后工作
SignalProducer
延后工作再悼,其輸出表示為值流核畴,直到它被啟動。每個調(diào)用啟動SignalProducer
冲九,就會創(chuàng)建一個新的Signal
谤草,并且延后工作被隨后調(diào)用。
let frames: SignalProducer<VideoFrame, ConnectionError> = vidStreamer.streamAsset(id: tvShowId)
let interrupter = frames.start { frame in ... }
interrupter.dispose()
4、Lifetime:限制觀察的范圍
當(dāng)在觀察Signal
或SignalProducer
中咖刃,如果不再有對象在觀察它們時泳炉,其就沒必要繼續(xù)發(fā)出值。細想流媒體:只要你停止觀看這個視頻一次嚎杨,這個流就會自動通過提供一個Lifetime
來關(guān)閉花鹅。
class VideoPlayer {
private let (lifetime, token) = Lifetime.make()
func play() {
let frames: SignalProducer<VideoFrame, ConnectionError> = ...
frames.take(during: lifetime).start { frame in ... }
}
}
5、Property:一個總持有值的可視的容器
Property
是一個可看得到其變化的變量枫浙。換句話說刨肃,其是一個比Signal
更有保證的值流,其最新的值總是可用并且這個流永遠不會失敗箩帚。
它就像視頻播放的持續(xù)更新的當(dāng)前時間偏移 - 播放總是在任何時候偏移一定的時間真友,并且隨著播放繼續(xù),它將會通過播放邏輯被更新紧帕。
let currentTime: Property<TimeInterval> = video.currentTime
print("Current time offset: \(currentTime.value)")
currentTime.signal.observeValues { timeBar.timeLabel.text = "\($0)" }
6盔然、Action:一系具有預(yù)設(shè)事件的行為
當(dāng)被輸入調(diào)用時,Action
將輸入和最新狀態(tài)應(yīng)用于預(yù)設(shè)事件是嗜,并將輸出推送給任何有興趣的方愈案。它就像一臺自動售貨機 - 在選擇了插入硬幣的選項后,機器會處理訂單并最終輸出您想要的零食鹅搪。
請注意站绪,整個過程是相互排斥的 - 您不能同時為兩個客戶服務(wù)。
// Purchase from the vending machine with a specific option.
vendingMachine.purchase
.apply(snackId)
.startWithResult { result
switch result {
case let .success(snack):
print("Snack: \(snack)")
case let .failure(error):
// Out of stock? Insufficient fund?
print("Transaction aborted: \(error)")
}
}
// The vending machine.
class VendingMachine {
let purchase: Action<Int, Snack, VendingMachineError>
let coins: MutableProperty<Int>
// The vending machine is connected with a sales recorder.
init(_ salesRecorder: SalesRecorder) {
coins = MutableProperty(0)
purchase = Action(state: coins, enabledIf: { $0 > 0 }) { coins, snackId in
return SignalProducer { observer, _ in
// The sales magic happens here.
// Fetch a snack based on its id
}
}
// The sales recorders are notified for any successful sales.
purchase.values.observeValues(salesRecorder.record)
}
}
7丽柿、參考文獻
有關(guān)ReactiveSwift中的概念和官方介紹的更多詳細信息恢准,請查看以下文檔:
Framework Overview
ReactiveSwift官方介紹和實用程序的行為和建議用例的綜述。
Basic Operators
提供組合和變換這些元方法的操作的綜述甫题。
Design Guidelines
ReactiveSwift元方法的規(guī)定和ReactiveSwift最佳實踐以及指導(dǎo)如何實現(xiàn)自定義操作馁筐。