你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> ReactiveCocoa 4 如何運用冷熱信號

ReactiveCocoa 4 如何運用冷熱信號

編輯:IOS開發綜合

ObjectiveCBridging

RACSignal -> Signal, SignalProducer

RACCommand -> Action

RACScheduler -> SchedulerType

RACDisposable -> Disposable

詳細可以參看ObjectiveCBridging.swift

什麼是ReactiveCocoa

什麼是信號

ReactiveCocoa的冷熱信號

RAC4的 Signal 對應RAC2的 RACSubject,為熱信號,SignalProducer 對應 RACSignal 為冷信號。

熱信號是自動的,就算沒有訂閱者也會即刻推送;冷信號是主動的,有訂閱者才推送

熱信號可以有多個訂閱者,一對多;冷信號只能一對一,當有新的訂閱者,信號是重新完好發送的

抽象的說:熱信號像是直播,冷信號像是點播

熱信號

參看一個例子

// 創立信號
let (signal, observer) = Signal.pipe()
// 監聽器1:立刻監聽
signal.observeResult {
    NSLog("Subscriber 1 get a next value: \($0)")
}
// 監聽器2:0.1s後監聽
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 0.1)) {
    signal.observeResult({ (result) in
        NSLog("Subscriber 2 get a next value: \(result)")
    })
}
// 發送Next信號:1s後發送"package 1"
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) { 
    NSLog("Signal send package 1 ...")
    observer.sendNext("package 1")
}
// 監聽器3:1.1s後監聽
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1.1)) { 
    signal.observeResult {
        NSLog("Subscriber 3 get a next value: \($0)")
    }
}
// 發送Next信號: 2s後發送"package 2"
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 2)) { 
    NSLog("signal send package 2 ...")
    observer.sendNext("package 2")
}

運轉:

2016-12-18 19:42:16.206588 TestRAC4[695:389286] start ...
2016-12-18 19:42:17.249072 TestRAC4[695:389286] Signal send package 1 ...
2016-12-18 19:42:17.254583 TestRAC4[695:389286] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 19:42:17.254899 TestRAC4[695:389286] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 19:42:18.393983 TestRAC4[695:389286] signal send package 2 ...
2016-12-18 19:42:18.394386 TestRAC4[695:389286] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 19:42:18.394582 TestRAC4[695:389286] Subscriber 2 get a next value: .Success(package 2)
2016-12-18 19:42:18.394769 TestRAC4[695:389286] Subscriber 3 get a next value: .Success(package 2)

正如之前提到的熱信號的特點,熱信號不關懷能否有人監聽,有發生信號就發送,有人監聽就發個監聽者。0.1s,2s辨別發送next事情,0s,0.1s,1.1s辨別發生一個監聽者,所以第一個信號只要監聽者1,2能收到;第二個next收回時三個監聽器都預備好了,都能收到。

冷信號

再看看冷信號的例子:

let producer = SignalProducer.init { (sink, _) in
    QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
        NSLog("Producer send package 1 ...")
        sink.sendNext("package 1")
    }
    QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 2)) {
        NSLog("Producer send package 2 ...")
        sink.sendNext("package 2")
    }
}
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 2)) {
    NSLog("setup Subsrciber 1")
    producer.startWithResult({ (msg) in
        NSLog("Subscriber 1 get a next value: \(msg)")
    })
}
QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 3)) {
    NSLog("setup Subsrciber 2")
    producer.startWithResult({ (msg) in
        NSLog("Subscriber 2 get a next value: \(msg)")
    })
}

以下是輸入:

2016-12-18 20:05:36.396118 TestRAC4[703:394073] start ...
2016-12-18 20:05:38.600637 TestRAC4[703:394073] setup Subsrciber 1
2016-12-18 20:05:39.681697 TestRAC4[703:394073] setup Subsrciber 2
2016-12-18 20:05:39.682077 TestRAC4[703:394073] Producer send package 1 ...
2016-12-18 20:05:39.685559 TestRAC4[703:394073] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 20:05:40.753463 TestRAC4[703:394073] Producer send package 2 ...
2016-12-18 20:05:40.753865 TestRAC4[703:394073] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 20:05:40.754679 TestRAC4[703:394073] Producer send package 1 ...
2016-12-18 20:05:40.754898 TestRAC4[703:394073] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 20:05:41.881230 TestRAC4[703:394073] Producer send package 2 ...
2016-12-18 20:05:41.881673 TestRAC4[703:394073] Subscriber 2 get a next value: .Success(package 2)

運用冷信號,信號在順序起來第1s,2s辨別發送了一個next。而在2s,3s辨別樹立了一個監聽。第一個監聽樹立後1s,2s辨別收到一個信號。第二信號樹立的1s,2s後也辨別收到了異樣的信號。

冷信號轉化為特殊熱信號

由於冷信號每次訂閱都重新發送事情,故有時分我們需求屢次訂閱時會形成不希望的反復發送(這稱為信號的反作用),我們需求將冷信號轉為具有熱信號特征的冷信號。

參看一個例子,我們用冷,熱信號在0.1s後發送三個next事情,然後如下停止監聽:

// 我們用2個監控來監控generateSignal()發生的信號 #1
let signal = generateSignal()

producer.startWithResult{ NSLog("Subscriber 1 get a next value: \($0)") }

QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
    producer.startWithResult{ NSLog("Subscriber 2 get a next value: \($0)") }
}

先看看假如是發生了普通的冷信號:

func generateSignal() -> SignalProducer {
    let producer = SignalProducer.init { (observer, _) in
        QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
            NSLog("producer send package 1 ...")
            observer.sendNext("package 1")
            NSLog("producer send package 2 ...")
            observer.sendNext("package 2")
            NSLog("producer send package 3 ...")
            observer.sendNext("package 3")
        }
    }
    return producer
}

輸入如我們所料,信號被反復發送了。

2016-12-18 21:46:21.295670 TestRAC4[742:413995] start ...
2016-12-18 21:46:22.389634 TestRAC4[742:413995] producer send package 1 ...
2016-12-18 21:46:22.397032 TestRAC4[742:413995] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 21:46:22.397397 TestRAC4[742:413995] producer send package 2 ...
2016-12-18 21:46:22.398235 TestRAC4[742:413995] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 21:46:22.398415 TestRAC4[742:413995] producer send package 3 ...
2016-12-18 21:46:22.398608 TestRAC4[742:413995] Subscriber 1 get a next value: .Success(package 3)
2016-12-18 21:46:23.496484 TestRAC4[742:413995] producer send package 1 ...
2016-12-18 21:46:23.496886 TestRAC4[742:413995] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 21:46:23.497061 TestRAC4[742:413995] producer send package 2 ...
2016-12-18 21:46:23.497255 TestRAC4[742:413995] Subscriber 2 get a next value: .Success(package 2)
2016-12-18 21:46:23.497413 TestRAC4[742:413995] producer send package 3 ...
2016-12-18 21:46:23.498869 TestRAC4[742:413995] Subscriber 2 get a next value: .Success(package 3)

假如改成熱信號呢?

func generateSignal() -> Signal {
    let (signal, observer) = Signal.pipe()
    QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 0.1)) {
        NSLog("producer send package 1 ...")
        observer.sendNext("package 1")
        NSLog("producer send package 2 ...")
        observer.sendNext("package 2")
        NSLog("producer send package 3 ...")
        observer.sendNext("package 3")
    }
    return signal
}

let signal = generateSignal()

signal.observeResult { NSLog("Subscriber 1 get a next value: \($0)") }

QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
    signal.observeResult{ NSLog("Subscriber 2 get a next value: \($0)") }
}

輸入也如我們所料,只要監聽2能搜到事情,且信號都只發送一次。

2016-12-18 21:54:34.527911 TestRAC4[745:415500] start ...
2016-12-18 21:54:34.634711 TestRAC4[745:415500] producer send package 1 ...
2016-12-18 21:54:34.637899 TestRAC4[745:415500] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 21:54:34.638067 TestRAC4[745:415500] producer send package 2 ...
2016-12-18 21:54:34.638146 TestRAC4[745:415500] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 21:54:34.638195 TestRAC4[745:415500] producer send package 3 ...
2016-12-18 21:54:34.638334 TestRAC4[745:415500] Subscriber 1 get a next value: .Success(package 3)
緩沖 buffer

經過SignalProducer.buffer()創立,是一個事情的隊列(通常指定數量),當新信號發生時,會重新執行隊列裡的事情。和pipe類似,這個辦法前往一個察看者。每個發給這個察看者的事情會被參加隊列。假如這個緩沖區曾經到達創立時預定的數量,當新的事情發來時,最早的一個會被移出隊列。

假如運用buffer來處置呢?我們將下面的冷信號稍作修正:

func generateSignal() -> SignalProducer {
    let (producer, observer) = SignalProducer.buffer(Int.max)
    QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
        NSLog("producer send package 1 ...")
        observer.sendNext("package 1")
        NSLog("producer send package 2 ...")
        observer.sendNext("package 2")
        NSLog("producer send package 3 ...")
        observer.sendNext("package 3")
    }
    return producer
}

輸入發現,似乎冷信號變成了熱信號了,只發送了一次。但又具有冷信號的特點:兩個監聽器都能收到事情。

2016-12-18 21:44:29.971493 TestRAC4[740:413482] start ...
2016-12-18 21:44:31.071352 TestRAC4[740:413482] producer send package 1 ...
2016-12-18 21:44:31.075839 TestRAC4[740:413482] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 21:44:31.076115 TestRAC4[740:413482] producer send package 2 ...
2016-12-18 21:44:31.076580 TestRAC4[740:413482] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 21:44:31.076773 TestRAC4[740:413482] producer send package 3 ...
2016-12-18 21:44:31.077035 TestRAC4[740:413482] Subscriber 1 get a next value: .Success(package 3)
2016-12-18 21:44:31.078167 TestRAC4[740:413482] Subscriber 2 get a next value: .Success(package 1)
2016-12-18 21:44:31.078420 TestRAC4[740:413482] Subscriber 2 get a next value: .Success(package 2)
2016-12-18 21:44:31.078771 TestRAC4[740:413482] Subscriber 2 get a next value: .Success(package 3)

buffer(Int.max)這裡的參數表示這個緩沖大小,假如設置為1,那麼訂閱者將只能收到最後一個next事情“package 3”;假如設置為2,只能收到最後兩個next事情“package 2”,“package 3”。

replayLazily

假設我們不能修generateSignal()裡的代碼,這是由第三方提供的,我們可以運用replayLazily。

let producer = generateSignal().replayLazily(Int.max)  // 直接用之前的冷信號

producer.startWithResult { NSLog("Subscriber 1 get a next value: \($0)") }

QueueScheduler.mainQueueScheduler.scheduleAfter(NSDate(timeIntervalSinceNow: 1)) {
    producer.startWithResult { NSLog("subscriber 2 get a next value: \($0)") }
}

輸入如下,和buffer是一樣的效果:

2016-12-18 22:04:48.364076 TestRAC4[753:417953] start ...
2016-12-18 22:04:48.482124 TestRAC4[753:417953] producer send package 1 ...
2016-12-18 22:04:48.484271 TestRAC4[753:417953] Subscriber 1 get a next value: .Success(package 1)
2016-12-18 22:04:48.484422 TestRAC4[753:417953] producer send package 2 ...
2016-12-18 22:04:48.484665 TestRAC4[753:417953] Subscriber 1 get a next value: .Success(package 2)
2016-12-18 22:04:48.484852 TestRAC4[753:417953] producer send package 3 ...
2016-12-18 22:04:48.485120 TestRAC4[753:417953] Subscriber 1 get a next value: .Success(package 3)
2016-12-18 22:04:49.454274 TestRAC4[753:417953] subscriber 2 get a next value: .Success(package 1)
2016-12-18 22:04:49.454659 TestRAC4[753:417953] subscriber 2 get a next value: .Success(package 2)
2016-12-18 22:04:49.454897 TestRAC4[753:417953] subscriber 2 get a next value: .Success(package 3)

那麼replayLazily(Int.max)這個參數和buffer的相反嗎?我們修正成1或2一看就知道。答案是相反

以上就是對ReactiveCocoa 4 如何運用冷熱信號的相關引見,希望對您學習IOS有所協助,感激您關注本站!

【ReactiveCocoa 4 如何運用冷熱信號】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

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