Subject
- 觀察者棘劣,繼承于
Publisher
,作為一個觀察者的身份银酬,可以監(jiān)聽其他源 - 被觀察者躲胳,可以發(fā)送數(shù)據(jù)流,提供給
Publisher
觀察數(shù)據(jù)變化 - 可以實現(xiàn)自定義的數(shù)據(jù)源皮服,內(nèi)置實現(xiàn)了幾個實例類
核心代碼
public protocol Subject: AnyObject, Publisher {
//發(fā)布數(shù)據(jù)流,Output是Publisher的輸入源類型
func send(_ value: Output)
//數(shù)據(jù)流完成的觸發(fā)方式
func send(completion: Subscribers.Completion<Failure>)
// 發(fā)送一個訂閱對象
func send(subscription: Subscription)
}
主要實現(xiàn)類
- CurrentValueSubject
- 會存儲send或者init存的流數(shù)據(jù),不會丟失
- 數(shù)據(jù)流如果觸發(fā)了完成龄广,后續(xù)再發(fā)送不會在收到數(shù)據(jù)流
- PassthroughSubject
- 首次不需要給初始值
- 數(shù)據(jù)流如果觸發(fā)了完成硫眯,后續(xù)再發(fā)送不會在收到數(shù)據(jù)流
- PublishedSubject
- @Published 注解內(nèi)部實現(xiàn)類
代碼演示
-
CurrentValueSubject 演示流程
let current = CurrentValueSubject<Int, Never>(1) current.send(2) /// `CurrentValueSubject` 會記錄最后一次send的值,當訂閱時候择同,會及時 發(fā)出去两入,相當于熱源 current.send(3) /// 訂閱 current.sink { debugPrint("current \($0)") }.store(in: &cancel) current.send(4) /// 發(fā)布完成以后,訂閱不會接收后續(xù)的數(shù)據(jù)流了 current.send(completion: .finished) current.send(5) /// 控制臺輸出: "current 3" "current 4" ```
-
PassthroughSubject
演示
let pass = PassthroughSubject<String, Never>()/// Pass /// `PassthroughSubject` 不會記錄數(shù)據(jù)奠衔,相當于冷源谆刨,訂閱后發(fā)出的數(shù)據(jù)流才會收到 pass.send("hello") /// 訂閱 pass.sink { debugPrint("pass \($0)") }.store(in: &cancel) pass.send("world") /// 發(fā)布完成,后續(xù)發(fā)送的數(shù)據(jù)流 不會再被訂閱接收 pass.send(completion: .finished) pass.send("over") /// 控制臺輸出 "pass world"
PublishedSubject
內(nèi)置注解類, 和CurrentSubject
實現(xiàn)方式類似归斤,但是不能發(fā)送完成事件
/// 回收類痊夭,頁面釋放需要調(diào)用cancel
lazy var cancel: [AnyCancellable] = []
/// 注解類 @Publish內(nèi)置是一個@propertywrapper 包裝了PublishedSubject
@Published var temperature: Double = 0
override func viewDidLoad() {
super.viewDidLoad()
self.temperature = 1
self.$temperature.sink { value in
debugPrint("value is : \(value)")
}.store(in: &cancel)
self.temperature = 2
self.temperature = 3
}
/// 控制器打印
"value is : 1.0"
"value is : 2.0"
"value is : 3.0"
```