有很多在給人介紹Reactive的幾個開源項目(ReactiveCocoa, RxSwift)的使用伦忠,我就不想在這個方面寫什么了翁锡。我是一個實踐主義者逮刨,所以我從我的角度來談?wù)勥@種方案:解決了什么樣的問題齐鲤,怎么實現(xiàn)的贪壳,以及適合應(yīng)用的場景饱亿。同時也加深自己對Reactive的理解。
這里我們來看看是怎么實現(xiàn)的,關(guān)于pure function
和monad
的部分我也不準備介紹了彪笼,畢竟我在這方面還不是特別熟悉钻注。
signal observer
首先我們來想一下一個最簡單信號的流程。當一個信號被訂閱時(subscribe)配猫,發(fā)出信號后會觸發(fā)訂閱者(observer)執(zhí)行下一步(sendNext)幅恋。那么一個最簡單的信號(signal)和訂閱者(observer)的協(xié)議就如下。
protocol Observer {
func send(next: AnyObject)
func send(error: NSError)
func sendComplete()
}
protocol Signal {
func subscribe(_ observer: ?Observer)
}
那么現(xiàn)在實現(xiàn)一個最簡單的UIButton的信號泵肄。
class ButtonSignal: Signal {
var observer: Observer?
init(button: UIButton) {
button .addTarget(self, action: #selector(onButton(sender:)), for: .touchUpInside)
}
@objc func onButton(sender: UIButton) {
self.observer?.send(next: sender)
}
func subscribe(_ observer: Observer) {
self.observer = observer
}
}
class ButtonSignal: Signal {
var observer: Observer?
init(button: UIButton) {
button .addTarget(self, action: #selector(onButton(sender:)), for: .touchUpInside)
}
func onButton(sender: UIButton) {
self.observer?.send(next: sender)
}
func subscribe(_ observer: Observer) {
self.observer = observer
}
}
然后實現(xiàn)一個最簡單的訂閱者捆交。
class ButtonObserver: Observer {
func send(next: AnyObject) {
print("send next!")
}
func sendComplete() {
print("send complete")
}
func send(error: NSError) {
print("send \(error)")
}
}
最后連接起來
signal = ButtonSignal(button: button)
signal?.subscribe(ButtonObserver())
那么問題來了,難道我們要為每個信號都創(chuàng)建一個類嗎腐巢。當然不是品追,我們可以創(chuàng)建一個通用的信號和訂閱者。
class BlockSignal: Signal {
typealias CreateBlock = (Observer)->Void
var block: CreateBlock
init(block:@escaping CreateBlock) {
self.block = block
}
func subscribe(_ observer: Observer) {
self.block(observer)
}
}
class BlockObserver: Observer {
var next: (AnyObject)->Void
var complete: ()->Void
var error: (NSError)->Void
init(next: @escaping (AnyObject)->Void,
complete: @escaping ()->Void,
error: @escaping (NSError)->Void) {
self.next = next
self.complete = complete
self.error = error
}
@objc func send(next: AnyObject) {
self.next(next)
}
func sendComplete() {
self.complete()
}
func send(error: NSError) {
self.error(error)
}
}
同時在使用的過程時通過block來創(chuàng)建具體信號冯丙。
signal = BlockSignal(block: { (observer) in
self.button.addTarget(observer,
action: #selector(BlockObserver.send(next:)),
for: .touchUpInside)
})
observer = BlockObserver(next: { (sender) in
print("send next!")
}, complete: {
print("send complete")
}) { (error) in
print("send error")
}
signal?.subscribe(observer!)
以上就是最簡單的信號量和訂閱者實現(xiàn)诵盼。這里為了簡潔的說明問題,所以沒有考慮到內(nèi)存方面的問題银还。
dispose
上節(jié)說了內(nèi)存方面的問題。還有一個問題就是如何取消訂閱呢洁墙。那么這里需要有模塊負責釋放(dispose)蛹疯。
那么將接口改為
protocol Disposable {
func dispose()
}
protocol Signal {
func subscribe(_ observer: Observer) -> Disposable
}
實現(xiàn)也按照block形式
class BlockDisposable: Disposable {
var block: ()->Void
init(block: @escaping ()->Void) {
self.block = block
}
func dispose() {
self.block()
}
}
class BlockSignal: Signal {
func subscribe(_ observer: Observer) -> Disposable {
return self.block(observer)
}
}
使用時和上面基本一致
signal = BlockSignal(block: { (observer) in
self.button.addTarget(observer,
action: #selector(BlockObserver.send(next:)),
for: .touchUpInside)
return BlockDisposable(block: {
self.button.removeTarget(observer,
action: #selector(BlockObserver.send(next:)),
for: .touchUpInside)
})
})
需要解除訂閱的時候
self.disposable = signal?.subscribe(observer!)
self.disposable?.dispose()
之后
到目前為止,可以說signal-observer部分已經(jīng)完全實現(xiàn)了热监。
其中冷信號和熱信號也非常簡單
protocol Subject: Observer, Signal {}
Scheduler也比較簡單捺弦,將執(zhí)行放到對應(yīng)的隊列中即可。
下篇結(jié)合我的角度來聊聊應(yīng)用場景孝扛。