Subject
- 觀察者,繼承于
Publisher,作為一個觀察者的身份,可以監(jiān)聽其他源 - 被觀察者,可以發(fā)送數(shù)據流,提供給
Publisher觀察數(shù)據變化 - 可以實現(xiàn)自定義的數(shù)據源,內置實現(xiàn)了幾個實例類
核心代碼
public protocol Subject: AnyObject, Publisher {
//發(fā)布數(shù)據流,Output是Publisher的輸入源類型
func send(_ value: Output)
//數(shù)據流完成的觸發(fā)方式
func send(completion: Subscribers.Completion<Failure>)
// 發(fā)送一個訂閱對象
func send(subscription: Subscription)
}
主要實現(xiàn)類
- CurrentValueSubject
- 會存儲send或者init存的流數(shù)據,不會丟失
- 數(shù)據流如果觸發(fā)了完成,后續(xù)再發(fā)送不會在收到數(shù)據流
- PassthroughSubject
- 首次不需要給初始值
- 數(shù)據流如果觸發(fā)了完成,后續(xù)再發(fā)送不會在收到數(shù)據流
- PublishedSubject
- @Published 注解內部實現(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ù)據流了 current.send(completion: .finished) current.send(5) /// 控制臺輸出: "current 3" "current 4" ``` -
PassthroughSubject演示
let pass = PassthroughSubject<String, Never>()/// Pass /// `PassthroughSubject` 不會記錄數(shù)據,相當于冷源,訂閱后發(fā)出的數(shù)據流才會收到 pass.send("hello") /// 訂閱 pass.sink { debugPrint("pass \($0)") }.store(in: &cancel) pass.send("world") /// 發(fā)布完成,后續(xù)發(fā)送的數(shù)據流 不會再被訂閱接收 pass.send(completion: .finished) pass.send("over") /// 控制臺輸出 "pass world" PublishedSubject內置注解類, 和CurrentSubject實現(xiàn)方式類似,但是不能發(fā)送完成事件
/// 回收類,頁面釋放需要調用cancel
lazy var cancel: [AnyCancellable] = []
/// 注解類 @Publish內置是一個@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"
```