CurrentValueSubject
和 PassthroughSubject
都是 Combine 框架中用于發(fā)布數(shù)據(jù)的 Publisher
類型,但它們在行為和用途上有一些關(guān)鍵的區(qū)別店读。
1. CurrentValueSubject
和 PassthroughSubject
的共同點
- 都是
Publisher
,可以向其訂閱者發(fā)布數(shù)據(jù)抛虏。 - 都屬于 Subject 類型年枕,在 Combine 中播歼,
Subject
是可以既作為 Publisher 也作為 Subscriber 的對象,允許你手動推送事件(發(fā)布數(shù)據(jù))蚓炬。
2. CurrentValueSubject
和 PassthroughSubject
的區(qū)別
CurrentValueSubject
:
類型定義:
CurrentValueSubject<Output, Failure>
特點:持有一個當(dāng)前值松逊,并允許你對這個值進(jìn)行讀取和更新。它會始終有一個初始值肯夏,并且可以隨時通過
send(_:)
方法發(fā)送新值经宏。行為:
CurrentValueSubject
需要一個初始值,因此在創(chuàng)建時必須傳入一個初始值驯击。如果沒有新的值發(fā)送烁兰,它會繼續(xù)向訂閱者發(fā)布當(dāng)前的值。初始值:它總是保持一個 當(dāng)前值徊都,并且可以通過
value
屬性直接訪問當(dāng)前值沪斟,且會始終向新的訂閱者發(fā)送該值。適用場景:當(dāng)你需要保持最新的狀態(tài)或者值暇矫,并且確保新的訂閱者能立刻收到當(dāng)前的值時主之,使用
CurrentValueSubject
很合適。
示例:
private let creditSubject = CurrentValueSubject<(), Never>(())
-
creditSubject
初始化時會持有()
(空元組)作為當(dāng)前值李根。 - 每次調(diào)用
creditSubject.send(())
會更新它的當(dāng)前值并向訂閱者發(fā)布新的值槽奕。 - 新的訂閱者會立刻收到
()
這個初始值。
PassthroughSubject
:
-
類型定義:
PassthroughSubject<Output, Failure>
- 特點:沒有初始值朱巨。它只是將它接收到的所有值轉(zhuǎn)發(fā)給訂閱者,而不存儲任何值枉长。
-
行為:當(dāng)你通過
send(_:)
方法發(fā)送數(shù)據(jù)時冀续,PassthroughSubject
會將數(shù)據(jù)立即傳遞給所有的訂閱者琼讽。它不像CurrentValueSubject
那樣持有或緩存當(dāng)前的值。 -
適用場景:當(dāng)你只關(guān)心信號的發(fā)送而不需要存儲值時洪唐,使用
PassthroughSubject
钻蹬。比如說,當(dāng)你只關(guān)心事件的發(fā)生凭需,而不需要訂閱者知道事件發(fā)生時的任何“狀態(tài)”问欠。
示例:
let pickPhotoResultSubject = PassthroughSubject<PickResult, Never>()
-
pickPhotoResultSubject
沒有初始值,它只是用來傳遞PickResult
類型的值粒蜈。 - 每次調(diào)用
pickPhotoResultSubject.send(pickResult)
會立即將pickResult
發(fā)送給所有的訂閱者顺献。 - 新的訂閱者不會立刻收到任何值,只有當(dāng)數(shù)據(jù)通過
send(_:)
被發(fā)布時才會收到數(shù)據(jù)枯怖。
3. 主要區(qū)別
特性 | CurrentValueSubject |
PassthroughSubject |
---|---|---|
初始值 | 有初始值注整,必須提供一個初始值 | 沒有初始值 |
值存儲 | 存儲當(dāng)前值,可以通過 value 屬性獲取當(dāng)前值 |
不存儲任何值度硝,只是轉(zhuǎn)發(fā)接收到的值 |
訂閱行為 | 新的訂閱者會收到當(dāng)前值 | 新的訂閱者不會收到任何值肿轨,只有在數(shù)據(jù)發(fā)送后才會接收到 |
用途 | 用于需要存儲并共享當(dāng)前狀態(tài)的場景 | 用于單純的事件通知或信號的轉(zhuǎn)發(fā) |
4. 示例對比:
CurrentValueSubject
示例
// 初始值是 0
private let subject = CurrentValueSubject<Int, Never>(0)
// 訂閱者 1
subject.sink(receiveValue: { value in
print("Subscriber 1: \(value)") // 會立即打印 "Subscriber 1: 0"
})
// 發(fā)送新的值
subject.send(1)
// 訂閱者 2
subject.sink(receiveValue: { value in
print("Subscriber 2: \(value)") // 會打印 "Subscriber 2: 1"
})
-
輸出:
Subscriber 1: 0 Subscriber 1: 1 Subscriber 2: 1
PassthroughSubject
示例
// 沒有初始值
private let subject = PassthroughSubject<Int, Never>()
// 訂閱者 1
subject.sink(receiveValue: { value in
print("Subscriber 1: \(value)")
})
// 發(fā)送新的值
subject.send(1)
// 訂閱者 2
subject.sink(receiveValue: { value in
print("Subscriber 2: \(value)")
})
-
輸出:
Subscriber 1: 1 Subscriber 2: 1
在這個例子中,PassthroughSubject
并沒有提供初始值蕊程,而是當(dāng)事件通過 send
發(fā)送時椒袍,才會將值轉(zhuǎn)發(fā)給訂閱者。新的訂閱者在接收到事件時才會收到值藻茂。