從實現(xiàn)角度看ReativeX

有很多在給人介紹Reactive的幾個開源項目(ReactiveCocoa, RxSwift)的使用伦忠,我就不想在這個方面寫什么了翁锡。我是一個實踐主義者逮刨,所以我從我的角度來談?wù)勥@種方案:解決了什么樣的問題齐鲤,怎么實現(xiàn)的贪壳,以及適合應(yīng)用的場景饱亿。同時也加深自己對Reactive的理解。

這里我們來看看是怎么實現(xiàn)的,關(guān)于pure functionmonad的部分我也不準備介紹了彪笼,畢竟我在這方面還不是特別熟悉钻注。

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)用場景孝扛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末列吼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子苦始,更是在濱河造成了極大的恐慌寞钥,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陌选,死亡現(xiàn)場離奇詭異理郑,居然都是意外死亡,警方通過查閱死者的電腦和手機咨油,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門您炉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人役电,你說我怎么就攤上這事赚爵。” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵冀膝,是天一觀的道長唁奢。 經(jīng)常有香客問我,道長畸写,這世上最難降的妖魔是什么驮瞧? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮枯芬,結(jié)果婚禮上论笔,老公的妹妹穿的比我還像新娘。我一直安慰自己千所,他們只是感情好狂魔,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著淫痰,像睡著了一般最楷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上待错,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天籽孙,我揣著相機與錄音,去河邊找鬼火俄。 笑死犯建,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的瓜客。 我是一名探鬼主播适瓦,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谱仪!你這毒婦竟也來了玻熙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤疯攒,失蹤者是張志新(化名)和其女友劉穎嗦随,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敬尺,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡称杨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了筷转。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姑原。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖呜舒,靈堂內(nèi)的尸體忽然破棺而出锭汛,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布唤殴,位于F島的核電站般婆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏朵逝。R本人自食惡果不足惜蔚袍,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望配名。 院中可真熱鬧啤咽,春花似錦、人聲如沸渠脉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芋膘。三九已至鳞青,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間为朋,已是汗流浹背臂拓。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留习寸,地道東北人埃儿。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像融涣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子精钮,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

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